带GridView的C#WPF ListView-添加/删除列上下文菜单

带GridView的C#WPF ListView-添加/删除列上下文菜单,c#,wpf,gridview,contextmenu,gridviewcolumn,C#,Wpf,Gridview,Contextmenu,Gridviewcolumn,我正在尝试向ListView添加上下文菜单(使用GridView)以切换列可见性。这是一个简单的菜单-它只有一个所有可用列的列表,如果选中了列名,该列应该是可见的 我的ListView显示为GridView。每个列的GridViewColumnHeader都有一个Name属性和Header属性,与具有相同名称和标题值的ContextMenu菜单项相匹配。我的问题是,如果不遍历所有列,我就无法通过GridViewColumnHeader的名称选择GridViewColumn 我可以按索引选择列,但

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

我的ListView显示为GridView。每个列的GridViewColumnHeader都有一个Name属性和Header属性,与具有相同名称和标题值的ContextMenu菜单项相匹配。我的问题是,如果不遍历所有列,我就无法通过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...

看起来没有用于此的内置方法。 您可以使用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;
}
private Dictionary\u columns=new Dictionary();
公共主窗口()
{
初始化组件();
gv.Columns.CollectionChanged+=Columns\u CollectionChanged;
}
私有无效列\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
如果((e.Action==NotifyCollectionChangedAction.Remove
||e.Action==NotifyCollectionChangedAction.Replace)
&&e.OldItems!=null)
{
foreach(e.OldItems中的GridViewColumn oldItem)
{
如果(_columns.ContainsKey(oldItem.Header))_columns.Remove((oldItem.Header));
}
}
如果(如NewItems!=null)
{
foreach(e.NewItems中的GridViewColumn newItem)
{
_列[newItem.Header]=newItem;
}
}
}
私有无效窗口\u关闭(对象发送方,System.ComponentModel.CancelEventArgs e)
{
尝试
{
gv.Columns.CollectionChanged-=Columns\u CollectionChanged;
}
捕获{}
}
私有GridViewColumn GetColumn(字符串标题)
{
GridViewColumn=null;
_columns.TryGetValue(标题,out列);
返回列;
}