0

我正在尝试将上下文菜单添加到 ListView(使用 GridView)以切换列的可见性。这是一个简单的菜单——它只有一个所有可用列的列表,如果选中了列名,该列应该是可见的。

我的 ListView 与 GridView 一起显示。每列的 GridViewColumnHeader 具有与具有相同 Name 和 Header 值的 ContextMenu MenuItem 匹配的 Name 属性和 Header 属性。我的问题是我无法弄清楚如何在遍历所有列的情况下通过其 GridViewColumnHeader 的名称来选择 GridViewColumn。

我可以按索引选择一列,但这不起作用,因为如果用户对列重新排序,列索引会发生变化。

有没有办法按标题数据选择一列?我在想这样的事情:

MenuItem m = e.Source as MenuItem;
GridView gv = (GridView)list.View;
GridViewColumn gvc = gv.Columns[m.Name];
//code to make width 0 or Auto goes here...
4

1 回答 1

0

看起来没有内置的方法。您可以使用 LINQ 表达式:

var col = gv.Columns.FirstOrDefault(it => it.Header == "name");

但它会遍历里面的列。我相信迭代会很快。另一种完全避免迭代的方法是订阅CollectionChanged事件并保存列标题和列之间的映射。但这是一种棘手的方式。

private Dictionary<object, GridViewColumn> _columns = new Dictionary<object, GridViewColumn>();

public MainWindow()
{
    InitializeComponent();
    gv.Columns.CollectionChanged += Columns_CollectionChanged;
}

private void Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
   if((e.Action==NotifyCollectionChangedAction.Remove 
       || e.Action==NotifyCollectionChangedAction.Replace)
       && e.OldItems!=null)
   {
       foreach(GridViewColumn oldItem in e.OldItems)
       {
           if(_columns.ContainsKey(oldItem.Header)) _columns.Remove((oldItem.Header));
       }
   }
   if(e.NewItems!=null)
   {
       foreach(GridViewColumn newItem in e.NewItems)
       {
           _columns[newItem.Header] = newItem;
       }
   }
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
   try
   {
        gv.Columns.CollectionChanged -= Columns_CollectionChanged;
    }
    catch { }
}

private GridViewColumn GetColumn(string header)
{
    GridViewColumn column = null;
    _columns.TryGetValue(header, out column);
    return column;
}
于 2014-03-25T16:35:37.673 回答