【问题标题】:How to get Design > Name property of DGV column from Header Text property如何从 Header Text 属性中获取 DGV 列的 Design > Name 属性
【发布时间】:2021-09-29 15:24:55
【问题描述】:

我正在尝试检查 CheckedListBox1 中未选中的项目,并根据返回的值隐藏 DataGridView1 中的相关列,但问题是 CheckedListBox1 中显示的值是 DGV 列的 HeaderText 属性而不是 Name 属性在 DGV 中隐藏该列是必需的。

见以下代码:

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

在引用列的 HeaderText 属性时,有没有办法检索 DGV 列的“名称”属性?

【问题讨论】:

  • 请删除VBA 标签,因为它与您的问题无关。

标签: vb.net winforms datagridview datagridviewcolumn


【解决方案1】:

您不需要列名来隐藏列。你需要这个专栏。名称只是获取列的一种手段。问题在于您填充CheckedListBox 的方式。显示HeaderText 非常有意义,因为这是用户实际看到的。您应该做的是将列本身放入CheckedListBox 并仅显示HeaderText。这样,项目就是列,例如

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

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

你发布的代码就变成了这样:

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

    column.Visible = CheckedListBox1.GetItemChecked(i)
Next

请注意,您通常应该在绑定时最后设置DataSource,但这似乎不适用于CheckedListBox,它不正式支持数据绑定。因此,首先设置DataSource

编辑:

在将评论添加到有关ItemCheck 事件和启动时检查项目的问题中后,我将添加此内容。这里的关键是在列表初始化之前不要实际对事件采取行动,即所有项目都已被初始检查。一种方法是这样的:

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

另一种方法是通过在初始化发生时不处理事件来防止引发事件。这可以通过多种方式完成,但如果您想这样做,我会将其作为练习留给您。

由于ItemCheck 事件在项目状态更改之前引发,因此您需要区别对待当前项目与其他项目。我上面的循环会变成这样:

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

也就是说,如果最初检查了所有项目并且所有列最初都是可见的,那么它只是您需要关心的当前项目,因此根本不需要循环:

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

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

【讨论】:

  • 是的,我删除了评论,认为您可能还没有看到它,因为我重新阅读了答案并尝试了它并且它起作用了......头脑太热......只是玩弄代码你提供的仍然有一个问题,它不一定总是在未选中项目时该列变为可见 = False,似乎当取消勾选一个,然后另一个它搞砸了,然后取消勾选 = 可见或勾选 = 不可见.
  • 我已将绑定代码更改为正常工作的代码。
  • 几乎可以肯定您遇到了问题,因为在项目状态更改之前引发了ItemCheck。出于这个原因,您必须以与其他项目不同的方式对待被选中或未选中的项目。不过,这超出了本问题的范围,因此您应该尝试使用我提供的有关该事件的信息,如果您仍然需要帮助,请发布另一个问题。
  • 好的,谢谢。由于我最喜欢您的解决方案,将列绑定到 CheckedListBox1 我将继续这样做,如果无法解决将发布另一个问题,目标将是其他问题。这个问题中的问题是通过您的绑定建议解决的(我也确实使用了 isLoaded 变量的建议:))
  • @Pawel,我决定,鉴于我已经将ItemCheck 事件合并到我的答案中,如何正确使用它是相关的。因此,我扩展了我的解决方案。
【解决方案2】:

试试这个:

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 

注意:System.Linq 是必填项!

[编辑]

此代码在 .ItemCheck 事件中执行。表单启动时 我遍历所有可用的列,填充 CheckedBoxList1 并作为 默认它们是未选中的,但我希望它们被选中,因为我想要 列在开始时可见

如果您想更改 CheckListBox 中当前选定项的列的可见性(在 ItemCheck 事件中),请使用:

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)

你看出区别了吗?

主要区别在于:没有foreach 循环;)

【讨论】:

  • 它可以工作...但是由于某种原因,当我加载表单时,除了 1 之外的所有列都被隐藏了,当我取消选中 CheckedListBox1 中的值时它们是可见的。只是想弄清楚 LINQ 来修复它,但您可能能够更快地发现它......
  • 添加,此代码在 .ItemCheck 事件中执行。当表单启动时,我遍历所有可用列,填充 CheckedBoxList1 并且默认情况下它们未选中,但我希望它们被选中,因为我希望这些列在开始时可见,所以我遍历它们并检查它们,这可能与此问题有关,因为您提供的代码将在加载表单时在每列检查中执行。
  • 有道理,我会相应地更新问题......我现在明白我应该展示填充控件等的整个过程,这将使这个线程更容易阅读任何人否则。
  • @MaciejLos 谢谢,我会保留你的代码,因为它会向我介绍更多 LINQ,尽管对于这个问题,我将使用 jmcilhinney 的解决方案。谢谢!
  • 我很抱歉。我错误地认为这个答案中的一些cmets实际上是在问题本身上。我显然没有向上滚动足够远。我将在这里删除我的 cmets。
猜你喜欢
  • 2014-12-02
  • 2015-02-25
  • 1970-01-01
  • 2018-07-17
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多