首页 > 解决方案 > 隐藏/禁用 ListView 列(不是 width=0 Hack)

问题描述

我们正在重新设计我们的列表视图,以允许用户选择他想要显示的列。

为了Key-To-Column-Index在填充列表视图时不搞乱转换,我们希望保持列的“基本”顺序,然后使用显示索引和(?)某些列上的可见属性来调整视图。

即基本表看起来像

id | name | date

它充满了像

ListViewItem lvi = new ListViewItem();
lvi.Text = someObject.ID;
lvi.SubItems.Add(someObject.Name);
lvi.SubItems.Add(someObject.Date);
...
ListView1.Items.AddRange(CollectionOfListViewItems);

如果用户现在选择了显示顺序id | date | name,这可以通过简单地更改某个列的 displayindex 值来轻松实现(无需修改生成 ListViewItems 的代码)。

但是,如果用户想要排除一列,通常的做法是将宽度设置为 0。但这会导致不良行为,即尝试扩展任何列的人有时只是扩展宽度为 0 的列并且感到困惑这是怎么回事。

有没有办法正确地隐藏列而不显示,而不实际从列表视图中删除该列?(因为删除列需要调整生成代码,否则标题/值不再正确对齐)。

标签: c#winformslistview

解决方案


我现在width=0用 - 让我们称之为 - hack 扩展了displayIndex=0hack。奇迹般有效:

迭代 1:我们根据定义继续添加列,因此我们不需要重构任何依赖于该列顺序的代码:

foreach (ColumnDefinition cd in this.ColumnDefinitions)
{
    ColumnHeader ch = new ColumnHeader();
    ch.Name = cd.Name;
    ch.Tag = cd;
    ch.Text = cd.Text;

    this.extendedListView.Columns.Add(ch);
}

迭代 2:为了尊重用户的显示顺序,我们修改displayIndex上面提到的,只要所有列都添加到列表视图中:

foreach (ColumnHeader ch in this.extendedListView.Columns)
{
    //DisplayIndex known?
    if (keyToIndex.ContainsKey(ch.Name))
    {
        int idx = keyToIndex[ch.Name];
        ch.DisplayIndex = idx;
    }
}

注意:用户取消选择的列没有存储在配置中的显示索引。所以它们现在漂浮在某个地方(宽度为 0),导致在尝试扩展另一列时它们可能被扩展的问题。

迭代 3:为了克服这个问题,我们只是再次迭代,并将每个不可见列推到索引 0。任何用户都不应尝试通过单击最左侧可见列的左侧来调整列的大小

//Avoid inivisble columns (width 0) beeing stuck somewhere in between. 
//push them all to the front, cause no one will try to expand the "0st Column".
foreach (ColumnHeader ch in this.extendedListView.Columns)
{
    //DisplayIndex not known?
    if (!keyToIndex.ContainsKey(ch.Name))
    {
        ch.DisplayIndex = 0;
        ch.Width = 0;
    }
}

推荐阅读