Search code examples
c#wpfwpf-controlscontextmenuwpfdatagrid

Placing a context menu on the last Data Column of Data Grid to control the visibility of other columns in WPF


How can I place a context menu on the last Data Column of DataGrid such that it can control the visibility of other columns.

I have a Data grid with total 8 columns. How can i place a context menu on the last column ? Need to understand if there exist is any possibility to control the visibility of other columns from the context menu (as shown in image below) ?

<DataGrid  x:Name="MyGrid" ItemsSource="{Binding obvCollection}" AutoGenerateColumns="False" > 
        <DataGridTemplateColumn Header = "Column 1"/>
        <DataGridTemplateColumn Header = "Column 2"/>
        <DataGridTemplateColumn Header = "Column 3"/>
        <DataGridTemplateColumn Header = "Column 4"/>
        <DataGridTemplateColumn Header = "Column 5"/>
        <DataGridTemplateColumn Header = "Column 6"/>
        <DataGridTemplateColumn Header = "Column 7"/>
        <DataGridTemplateColumn Header = "Column 8"/>
        <DataGridTemplateColumn Header = ""/>
    </Datagrid>     

Solution

  • You could implement this with a converter:

    class VisibilityToBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Visibility visibility = (Visibility)value;
            return visibility == Visibility.Visible;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool b = (bool)value;
            return b ? Visibility.Visible : Visibility.Hidden;
        }
    }
    

    ...and some XAML markup:

    <DataGridTemplateColumn>
        <DataGridTemplateColumn.Header>
            <Grid Background="Gray" Width="25" Height="25"
                  Tag="{Binding Columns, ElementName=MyGrid}">
                <Grid.ContextMenu>
                    <ContextMenu ItemsSource="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                        <ContextMenu.ItemTemplate>
                            <DataTemplate>
                                <CheckBox x:Name="chk">
                                    <CheckBox.IsChecked>
                                        <Binding Path="Visibility">
                                            <Binding.Converter>
                                                <local:VisibilityToBooleanConverter />
                                            </Binding.Converter>
                                        </Binding>
                                    </CheckBox.IsChecked>
                                    <CheckBox.Content>
                                        <TextBlock Text="{Binding Header}" />
                                    </CheckBox.Content>
                                </CheckBox>
                                <DataTemplate.Triggers>
                                    <!-- hide the last column in the ContentMenu-->
                                    <DataTrigger Binding="{Binding DisplayIndex}" Value="5">
                                        <Setter TargetName="chk" Property="Visibility" Value="Collapsed" />
                                    </DataTrigger>
                                </DataTemplate.Triggers>
                            </DataTemplate>
                        </ContextMenu.ItemTemplate>
                    </ContextMenu>
                </Grid.ContextMenu>
            </Grid>
        </DataGridTemplateColumn.Header>
    </DataGridTemplateColumn>
    

    Replace the Grid in the sample markup with a hamburger button or whatever element you want the user to click on to bring up the ContextMenu.