following a discussion in the comments of this post…
this is the WPF version of a DataGrid control with integrated columns chooser that opens when right-clicking one of the headers.
(see Silverlight demo)
full source code over here
this is how it look like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace WPF_DataGridWithColumnChooser.Controls
{
public class DataGridExtended : DataGrid
{
public DataGridExtended()
: base()
{
theContextMenu = new ContextMenu();
this.Columns.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Columns_CollectionChanged);
}
private ContextMenu theContextMenu; //context menu for the field chooser.
private string AllColumnsHeaders { get; set; }
private bool oneTime = true;
protected override Size ArrangeOverride(Size finalSize)
{
if (oneTime)// do this only once.
{
oneTime = false;
var headersPresenter = FindChild(this);
// attach the context menu.
ContextMenuService.SetContextMenu(headersPresenter, theContextMenu);
// update VisibleColumns as necessary.
if (String.IsNullOrEmpty(VisibleColumns))
{
VisibleColumns = AllColumnsHeaders;
}
else
{
string s = VisibleColumns;
VisibleColumns = null;
VisibleColumns = s;
}
}
return base.ArrangeOverride(finalSize);
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MenuItem mi = sender as MenuItem;
Image icon = (Image)mi.Icon;
List splited = VisibleColumns.Split(';').ToList();
string colName = mi.Header.ToString();
// remove empty items.
for (int i = 0; i 1)
{
splited.Remove(colName);
}
}
// update the VisibleColumns.
string build = "";
foreach (string name in splited)
{
build = string.Format("{0};{1}", name, build);
}
VisibleColumns = build;
}
private void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
DataGridColumn col = e.NewItems[0] as DataGridColumn;
// keep a list of all clomuns headers for later use.
AllColumnsHeaders = String.Format("{0};{1}", col.Header.ToString(), AllColumnsHeaders);
// make a new menu item and add it to the context menu.
MenuItem menuItem = new MenuItem();
Image img;
menuItem.Click += new RoutedEventHandler(MenuItem_Click);
menuItem.Header = col.Header.ToString();
img = new Image();
img.Source = Application.Current.Resources["Vmark"] as ImageSource;
menuItem.Icon = img;
theContextMenu.Items.Add(menuItem);
}
#region VisibleColumns (DependencyProperty)
/// <summary>
/// Gets or sets a value indicating the names of columns (as they appear in the column header) to be visible, seperated by a semicolon.
/// columns that whose name is not here will be hidden.
/// </summary>
public string VisibleColumns
{
get { return (string)GetValue(VisibleColumnsProperty); }
set { SetValue(VisibleColumnsProperty, value); }
}
public static readonly DependencyProperty VisibleColumnsProperty =
DependencyProperty.Register(
"VisibleColumns",
typeof(string),
typeof(DataGridExtended),
new PropertyMetadata("", new PropertyChangedCallback(OnVisibleColumnsChanged))
);
private static void OnVisibleColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DataGridExtended dg = (DataGridExtended)d;
dg.VisibleColumnsChanged(e);
}
private void VisibleColumnsChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null)
{
string[] showTheseColumns = e.NewValue.ToString().Split(';');
string colName;
// update the columns visibility.
foreach (DataGridColumn col in this.Columns)
{
colName = col.Header.ToString();
if (showTheseColumns.Contains(colName))
col.Visibility = Visibility.Visible;
else
col.Visibility = Visibility.Collapsed;
}
// update the context menu items.
if (theContextMenu != null)
{
foreach (MenuItem menuItem in theContextMenu.Items)
{
colName = menuItem.Header.ToString();
if (showTheseColumns.Contains(colName))
((Image)menuItem.Icon).Visibility = Visibility.Visible;
else
((Image)menuItem.Icon).Visibility = Visibility.Collapsed;
}
}
}
}
#endregion
public static T FindChild(DependencyObject depObj) where T : DependencyObject
{
// Confirm obj is valid.
if (depObj == null) return null;
// success case
if (depObj is T)
return depObj as T;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
T obj = FindChild(child);
if (obj != null)
return obj;
}
return null;
}
}
}