Search code examples
c#wpfmvvmdatagriddatagridcolumnheader

How to get Data Grid column index on right click? MVVM WPF


I want to get column Index and pass it by CommandParameter I have, in a context menu for Data grid column header.

<DataGrid.Resources>
     <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
           <MenuItem Header="Freez Column"
                     Command="{Binding DataContext.FreezColumnCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                     CommandParameter="{Binding}" />
     </ContextMenu>
     <Style TargetType="{x:Type DataGridColumnHeader}">
           <Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderContextMenu}" />
     </Style>
</DataGrid.Resources>

I've tried to pass the entire object by passing Binding in CommandParameter, but it only passes the header text.

And tried using RelateveSource AncestorType=DataGridColumn still couldn't figure it out.

Edit:

DataGrid code:

<DataGrid ItemsSource="{Binding MyList}" HorizontalScrollBarVisibility="Visible" CanUserAddRows="False" AutoGenerateColumns="False">
     <DataGrid.Resources>
          <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
               <MenuItem Header="Freez Column"
                         Command="{Binding DataContext.FreezColumnCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                         CommandParameter="{Binding}" />
          </ContextMenu>
          <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderContextMenu}" />
          </Style>
     </DataGrid.Resources>
     <DataGrid.Columns>
          <DataGridTextColumn Header="Story" Binding="{Binding Story}" />
          <DataGridCheckBoxColumn Header="Design" Binding="{Binding Design}" />
          <DataGridTextColumn Header="CadId" Binding="{Binding CadId}" />
     </DataGrid.Columns>
</DataGrid>

Solution

  • This is happening probably because of ContextMenu is maintained in separate VisualTree(correct me if i'm wrong). Please use the below code to get DisplayIndex,

      <DataGrid
            x:Name="myGrid"
            AutoGenerateColumns="False"
            CanUserAddRows="False"
            HorizontalScrollBarVisibility="Visible"
            ItemsSource="{Binding Persons}">
            <DataGrid.Resources>
                <local:GridToIndexConverter x:Key="GridToIndexConverter" />
                <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
                    <MenuItem
                        Command="{Binding DataContext.FreezColumnCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                        CommandParameter="{Binding PlacementTarget.DisplayIndex, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"
                        Header="Freez Column" />
                </ContextMenu>
                <Style TargetType="{x:Type DataGridColumnHeader}">
                    <Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderContextMenu}" />
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Story}" Header="Story" />
                <DataGridCheckBoxColumn Binding="{Binding Design}" Header="Design" />
                <DataGridTextColumn Binding="{Binding CadId}" Header="CadId" />
            </DataGrid.Columns>
        </DataGrid>
    

    i have accessed PlacementTarget of ContextMenu.