Joe
Joe

Reputation: 651

How to add a right click context menu to Column Header for a WPF 4 DataGrid?

I want the context menu for a DataGrid's column headers to be different than the rest of the cells. So using the regular ContextMenu property is not going to work. There is DataGrid.RowHeaderTemplate, but I can't find DataGrid.ColumnHeaderTemplate.

Edit/Note: Columns are generated dynamically.

Upvotes: 17

Views: 19085

Answers (3)

Chandraprakash
Chandraprakash

Reputation: 978

If you want this to be done fully on code behind below is the approach.

using System.Windows.Controls.Primitives;
    
private void dgFormat_PreviewMouseRightButtonDown(object sender,
                                                  MouseButtonEventArgs e)
{            
    ContextMenu cm = new ContextMenu();
    
    MenuItem miOne = new MenuItem();
    miOne.Header = "One";
    miOne.Click += MiOne_Click;

    MenuItem miTwo = new MenuItem();
    miTwo.Header = "Two";
    miTwo.Click += MiTwo_Click;

    cm.Items.Add(miOne);
    cm.Items.Add(miTwo);
    
    dgFormat.ContextMenu = cm;
    dgFormat.ContextMenu.Visibility = Visibility.Collapsed;

    DependencyObject depObj = (DependencyObject)e.OriginalSource;

    while (depObj != null &&
            !(depObj is DataGridColumnHeader))
    {
        depObj = VisualTreeHelper.GetParent(depObj);
    }

    if (depObj == null)
    {
        return;
    }

    if (depObj is DataGridColumnHeader)
    {
        DataGridColumnHeader colHeader = depObj as DataGridColumnHeader;

        if (colHeader.Content.ToString() == "First Name")
        {
            dgFormat.ContextMenu.Visibility = Visibility.Visible;
        }
    }
}
    
private void MiOne_Click(object sender,
                         RoutedEventArgs e)
{
    MessageBox.Show("One");
}
    
private void MiTwo_Click(object sender,
                         RoutedEventArgs e)
{
    MessageBox.Show("Two");
}

Upvotes: 1

Grokodile
Grokodile

Reputation: 3933

It depends on how you are generating your columns, if you are defining them in XAML then you could do this:

<DataGrid DataContext="{Binding MyDataContext}" ItemsSource="{Binding MyItems}" AutoGenerateColumns="False">        
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Path=Age}" Header="Age" >
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{TemplateBinding Content}" >
                        <TextBlock.ContextMenu>
                            <ContextMenu>
                                <MenuItem Header="Task _1" />
                                <MenuItem Header="Task _2" />
                                <MenuItem Header="Task _3" />
                            </ContextMenu>
                        </TextBlock.ContextMenu>
                    </TextBlock>
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

Upvotes: 1

Vinit Sankhe
Vinit Sankhe

Reputation: 19885

Target a common Style to all DataGridColumnHeaders:

    <DataGrid.Resources>
         <ContextMenu x:Key="DataGridColumnHeaderContextMenu" ...>
         </ContextMenu>

         <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="ContextMenu"
                    Value="{StaticResource DataGridColumnHeaderContextMenu}" />
         </Style>
   </DataGrid.Resources>

If you want different context menus for different column headers then use triggers:

     <DataGrid.Resources>
         <ContextMenu x:Key="ColumnHeaderContextMenu1" ...>
         </ContextMenu>

         <ContextMenu x:Key="ColumnHeaderContextMenu2" ...>
         </ContextMenu>

         <Style TargetType="{x:Type DataGridColumnHeader}">
             <Style.Triggers>
                <Trigger Property="Content" Value="Column1">
                    <Setter Property="ContextMenu"
                            Value="{StaticResource ColumnHeaderContextMenu1}" />
                </Trigger>
                <Trigger Property="Content" Value="Column2">
                    <Setter Property="ContextMenu"
                            Value="{StaticResource ColumnHeaderContextMenu2}" />
                </Trigger>
             </Style.Triggers>
        </Style>
   </DataGrid.Resources>

Hope that helps.

Upvotes: 31

Related Questions