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?
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)