public class DataGridColumnChooser
{
private DataGridColumnChooser(DataGrid dataGrid)
{
if (dataGrid == null)
{
throw new ArgumentNullException("dataGrid");
}
this.dataGrid = dataGrid;
}
private static readonly Dictionary<DataGrid, DataGridColumnChooser> choosers = new Dictionary<DataGrid, DataGridColumnChooser>();
private readonly DataGrid dataGrid;
private ContextMenu contextMenu;
private DataGridColumn currentColumn;
private bool isUnregistered;
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
// Using a DependencyProperty as the backing store for IsEnabledProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(DataGridColumnChooser), new UIPropertyMetadata(false, OnIsEnabledChanged));
private static void OnIsEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (e.Property != IsEnabledProperty)
{
return;
}
if (!(e.OldValue is bool) || !(e.NewValue is bool))
{
return;
}
bool oldIsEnabled = (bool)e.OldValue;
bool newIsEnabled = (bool)e.NewValue;
if (oldIsEnabled == newIsEnabled)
{
return;
}
if (dependencyObject == null)
{
throw new ArgumentNullException("dependencyObject");
}
DataGrid dataGrid = dependencyObject as DataGrid;
if (dataGrid == null)
{
string message = String.Format(CultureInfo.CurrentCulture, "Parameter must be of type '{0}'.", typeof(DataGrid).FullName);
throw new ArgumentException(message, "dependencyObject");
}
if (oldIsEnabled)
{
if (choosers.ContainsKey(dataGrid))
{
choosers[dataGrid].Unregister();
choosers.Remove(dataGrid);
}
}
else
{
if (!choosers.ContainsKey(dataGrid))
{
DataGridColumnChooser chooser = new DataGridColumnChooser(dataGrid);
choosers[dataGrid] = chooser;
chooser.Register();
}
}
}
private void Unregister()
{
dataGrid.ColumnReordered -= OnColumnsReordered;
dataGrid.AutoGeneratedColumns -= OnAutogeneratedColumns;
dataGrid.ColumnDisplayIndexChanged -= OnColumnDisplayIndexChanged;
dataGrid.Columns.CollectionChanged -= OnColumnsCollectionChanged;
isUnregistered = true;
}
private void Register()
{
dataGrid.ColumnReordered += OnColumnsReordered;
dataGrid.AutoGeneratedColumns += OnAutogeneratedColumns;
dataGrid.ColumnDisplayIndexChanged += OnColumnDisplayIndexChanged;
dataGrid.Columns.CollectionChanged += OnColumnsCollectionChanged;
dataGrid.MouseRightButtonUp += OnMouseRightButtonUp;
BuildContextMenu();
}
private void BuildContextMenu()
{
if (contextMenu == null)
{
contextMenu = new ContextMenu();
}
foreach (MenuItem menuItem in contextMenu.Items.OfType<MenuItem>())
{
BindingOperations.ClearBinding(menuItem, MenuItem.IsCheckedProperty);
}
contextMenu.Items.Clear();
foreach (DataGridColumn dataGridColumn in dataGrid.Columns)
{
MenuItem menuItem = new MenuItem
{
Header = dataGridColumn.Header,
IsCheckable = true,
IsChecked = dataGridColumn.Visibility == Visibility.Visible
};
DataGridColumn tempColumn = dataGridColumn;
Binding binding = new Binding("Visibility")
{
Mode = BindingMode.TwoWay,
Converter = VisibilityToBooleanConverter.Instance,
Source = tempColumn,
};
BindingOperations.SetBinding(menuItem, MenuItem.IsCheckedProperty, binding).UpdateTarget();
contextMenu.Items.Add(menuItem);
}
}
private void OnMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
DependencyObject dependencyObject = (DependencyObject)e.OriginalSource;
while ((dependencyObject != null) && !(dependencyObject is DataGridColumnHeader))
{
dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
}
if (dependencyObject == null)
{
return;
}
if (dependencyObject is DataGridColumnHeader)
{
DataGridColumnHeader columnHeader = dependencyObject as DataGridColumnHeader;
currentColumn = columnHeader.Column;
columnHeader.ContextMenu = isUnregistered ? null : contextMenu;
}
else
{
currentColumn = null;
}
}
private void OnColumnsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
BuildContextMenu();
}
private void OnColumnDisplayIndexChanged(object sender, DataGridColumnEventArgs e)
{
BuildContextMenu();
}
private void OnAutogeneratedColumns(object sender, EventArgs e)
{
BuildContextMenu();
}
private void OnColumnsReordered(object sender, DataGridColumnEventArgs e)
{
BuildContextMenu();
}
#region Nested type: VisibilityToBooleanConverter
private class VisibilityToBooleanConverter : IValueConverter
{
#region Public Static Fields
public static readonly VisibilityToBooleanConverter Instance = new VisibilityToBooleanConverter();
#endregion
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility)
{
return ((Visibility)value) == Visibility.Visible;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
return DependencyProperty.UnsetValue;
}
#endregion
}
#endregion
}