0
votes

I'm trying to add a context menu to a ListView (using GridView) to toggle column visibility. It's a simple menu - it just has a list of all the available columns, and if the column name is checked, that column should be visible.

My ListView is displayed with a GridView. The GridViewColumnHeader for each column has a Name property and Header property that match with a ContextMenu MenuItem with the same Name and Header values. My problem is that I can't figure out how to select a GridViewColumn by its GridViewColumnHeader's name without iterating through all the columns.

I can select a column by index, but that won't work since the column index changes if the columns are reordered by the user.

Is there a way to select a column by header data? I'm thinking something like this:

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...
1

1 Answers

0
votes

Looks like there is no built in method for this. You can use LINQ expression:

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

but it will iterate through the columns inside. I believe iterating will be pretty fast. The other way to avoid iterating completely is to subscribe on CollectionChanged event and save mapping between column header and column. But this is tricky way.

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;
}