title: WPF DataGridColumnHeader: ContextMenu disappears after hiding/re-showing column
body: <p>I'm trying to come up with a System.Windows.Interactivity.Behaviour that, when applied to a WPF DataGrid, adds a context menu (or items to an existing context menu) that allow users to show or hide columns.</p>
  
  <p>I came up with a solution that <em>almost</em> works very well.
  Everything works just as expected - until you hide and then re-show a column. Once becoming visible again, the contextmenu just seems to disappear, right-clicking on the column doesn't do anything anymore.</p>
  
  <p>Code is below, verbalyl what I'm doing:</p>
  
  <ol>
  <li>On attaching the behavior, I start listening to the DataGrid "Loaded" event</li>
  <li>In the Loaded event, I find all DataGridColumnHeader descendants of the DataGrid</li>
  <li>For each of these, I generate an individual context menu and attach it to the DataGridColumnHeader</li>
  <li>For each context menu, I generate one menu item per column, and assign a command to it that, upon execution, sets the DataGridColumn's visibility to Visible or Hidden</li>
  </ol>
  
  <p>I've stripped down the code to a minimum example for the simplest case: To test this, simply apply that behavior to a DataGrid that doesn't have a ContextMenu assigned currently.</p>
  
  <pre><code>public class DgColumnBehavior : Behavior&lt;DataGrid&gt;
  {
      protected ICommand ToggleColumnVisibilityCmd;
      protected DataGrid _AssociatedObject;
  
      protected override void OnAttached()
      {
          this.ToggleColumnVisibilityCmd = new DelegateCommand&lt;DataGridColumn&gt;(ToggleColumnVisibilityCmdExecute);
          this._AssociatedObject = (DataGrid)this.AssociatedObject;
  
          Observable.FromEventPattern(this._AssociatedObject, "Loaded")
              .Take(1)
              .Subscribe(x =&gt; _AssociatedObject_Loaded());
  
          base.OnAttached();
      }
  
      void _AssociatedObject_Loaded()
      {
          var columnHeaders = this._AssociatedObject.SafeFindDescendants&lt;DataGridColumnHeader&gt;();  // see second code piece for the SafeFindDescendants extension method
  
          foreach (var columnHeader in columnHeaders)
          {
              EnsureSeparateContextMenuFor(columnHeader);
  
              if (columnHeader.ContextMenu.ItemsSource != null)
              {
                  // ContextMenu has an ItemsSource, so need to add items to that -
                  // ommitted though as irrelevant for example
              }
              else
              {
                  // No ItemsSource assigned to the Menu, so we can just add directly
  
                  foreach (var item in CreateMenuItemsFor(columnHeader))
                      columnHeader.ContextMenu.Items.Add(item);
              }
          }
      }
  
      /// Ensures that the columnHeader ...
      /// A) has a ContextMenu, and
      /// B) that is has an individual context menu, i.e. one that isn't shared with any other DataGridColumnHeaders.
      /// 
      /// I'm doing that as in practice, I'm adding some further items that are specific to each column, so I can't have a shared context menu
      private void EnsureSeparateContextMenuFor(DataGridColumnHeader columnHeader)
      {
          if (columnHeader.ContextMenu == null)
          {
              columnHeader.ContextMenu = new ContextMenu();
          }
          else
          {
              // clone the existing menu
              // ommitted as irrelevant for example
          }
      }
  
      /// Creates one menu item for each column of the underlying DataGrid to toggle that column's visibility
      private IEnumerable&lt;FrameworkElement&gt; CreateMenuItemsFor(DataGridColumnHeader columnHeader)
      {
          foreach (var column in _AssociatedObject.Columns)
          {
              var item = new MenuItem();
              item.Header = String.Format("Toggle visibility for {0}", column.Header);
              item.Command = ToggleColumnVisibilityCmd;
              item.CommandParameter = column;
  
              yield return item;
          }
      }
  
      // Gets executed when the user clicks on one of the ContextMenu items
      protected void ToggleColumnVisibilityCmdExecute(DataGridColumn column)
      {
          bool isVisible = (column.Visibility == Visibility.Visible);
          Visibility newVisibility = (isVisible) ? Visibility.Hidden : Visibility.Visible;
          column.Visibility = newVisibility;
      }
  }
  </code></pre>
  
  <p>The SafeFindDescendants extension method is heavily based on the one from here: <a href="https://stackoverflow.com/questions/13746689/datagridcolumnheader-contextmenu-programmatically">DataGridColumnHeader ContextMenu programmatically</a></p>
  
  <pre><code>public static class Visual_ExtensionMethods
  {
      public static IEnumerable&lt;T&gt; SafeFindDescendants&lt;T&gt;(this Visual @this, Predicate&lt;T&gt; predicate = null) where T : Visual
      {
          if (@this != null)
          {
              int childrenCount = VisualTreeHelper.GetChildrenCount(@this);
              for (int i = 0; i &lt; childrenCount; i++)
              {
                  var currentChild = VisualTreeHelper.GetChild(@this, i);
  
                  var typedChild = currentChild as T;
                  if (typedChild == null)
                  {
                      var result = ((Visual)currentChild).SafeFindDescendants&lt;T&gt;(predicate);
  
                      foreach (var r in result)
                          yield return r;
  
                  }
                  else
                  {
                      if (predicate == null || predicate(typedChild))
                      {
                          yield return typedChild;
                      }
                  }
              }
  
          }
      }
  }
  </code></pre>
  
  <p>I can't figure out what's going on. Why does the context menu seem to be removed after hiding/re-showing a column?!</p>
  
  <p>Appreciate any ideas! Thanks.</p>