2
votes

I am trying to go through un-checked items within a CheckedListBox1 and based on the values returned hide relevant columns within DataGridView1 but the issue is that the values displayed in CheckedListBox1 are the HeaderText property of DGV column and not the Name property which is required for hiding the column within DGV.

See below code:

For Each checked_item As Object In CheckedListBox1.Items
            If Not CheckedListBox1.CheckedItems.Contains(checked_item) Then
                DataGridView1.Columns("").Visible = False
            End If
        Next

Is there a way to retrieve "Name" property of DGV column when referencing the column's HeaderText property?

2
Please, remove VBA tag as it's not related to your question.Maciej Los

2 Answers

3
votes

You don't need the column name to hide the column. You need the column. The name is just a means to get the column. The issue is the way you're populating your CheckedListBox. Displaying the HeaderText makes perfect sense, because that's what the user actually sees. What you should be doing is putting the columns themselves into the CheckedListBox and just displaying the HeaderText. That way, the items are the columns, e.g.

Dim columns = DataGridView1.Columns.Cast(Of DataGridViewColumn)().ToArray()

With CheckedListBox1
    .DataSource = columns
    .DisplayMember = NameOf(DataGridViewColumn.HeaderText)
End With

The code you posted then becomes this:

For i = 0 To CheckedListBox1.Items.Count - 1
    Dim column = DirectCast(CheckedListBox1.Items(i), DataGridViewColumn)

    column.Visible = CheckedListBox1.GetItemChecked(i)
Next

Note that you should generally set the DataSource last when binding but that doesn't seem to work with a CheckedListBox, which doesn't offically support data-binding. For that reason, the DataSource is set first.

EDIT:

I'm adding this after the comment was added to the question about the ItemCheck event and the checking of the items at startup. The key here is to not actually act on the event until the list has been initialised, i.e. all the items have been initially checked. One way to do that would be like so:

Private isLoaded As Boolean = False

Private Sub Form1_Load(...) Handles MyBase.Load
    'Bind the data and check the items in the CheckedListBox here.

    isLoaded = True
End Sub

Private Sub CheckedListBox1_ItemCheck(...) CheckedListBox1.ItemCheck
    If isLoaded Then
        'Act here.
    End If
End Sub

The other way to is to prevent event being raised by not handling it while the initialisation is taking place. That can be done in a couple of ways but I'll leave that to you as an exercise if that's what you want to do.

As the ItemCheck event is raised before the state of an item changes, you will need to treat the current item differently to the other items. My loop above would become this:

For i = 0 To CheckedListBox1.Items.Count - 1
    Dim column = DirectCast(CheckedListBox1.Items(i), DataGridViewColumn)

    'For the item that is being checked/unchecked, use its new state.
    'For other items, use their current state.
    column.Visible = If(i = e.Index,
                        e.NewValue = CheckState.Checked,
                        CheckedListBox1.GetItemChecked(i))
Next

That said, if all items are initially checked and all columns are initially visible, it's only the current item that you need to care about, so there's no need for a loop at all:

Dim column = DirectCast(CheckedListBox1.Items(e.Index), DataGridViewColumn)

column.Visible = (e.NewValue = CheckState.Checked)
2
votes

Try this:

For Each checked_item As Object In CheckedListBox1.Items
        Dim oCol As DataGridViewColumn = DataGridView1.Columns _
            .Cast(Of DataGridViewColumn)() _
            .Where(Function(x) x.HeaderText = checked_item).SingleOrDefault()
        If oCol IsNot Nothing Then oCol.Visible = _
            Not CheckedListBox1.CheckedItems.Contains(checked_item)
Next 

Note: System.Linq is required!

[EDIT]

this code is executed in the .ItemCheck event. When the form starts up I loop through all available columns, populate CheckedBoxList1 and as default they are un-checked but I want them checked as I want the columns to be visible at start

If you would like to change the visibility of column of currently selected item in CheckListBox (in ItemCheck event), use this:

Dim oCol As DataGridViewColumn = DataGridView1.Columns _
    .Cast(Of DataGridViewColumn)() _
    .Where(Function(x) x.HeaderText = checked_item).SingleOrDefault()
If oCol IsNot Nothing Then oCol.Visible = _
    Not CheckedListBox1.CheckedItems.Contains(CheckedListBox1.SelectedItem)

Do you see the difference?

The main difference is: there's no foreach loop ;)