0

I am trying to make a simple TODO App with WPF using MVVM. I have the tasks in Datagrid and a right click context menu with Delete option. I don't want the context menu to show when there are no elements in Data Grid. What can I do to solve it?



<Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
            
        </Grid.RowDefinitions>



   <DataGrid  ItemsSource="{Binding Path=TaskList}" SelectedItem="{Binding SelectedTask}" AutoGenerateColumns="False">

            <DataGrid.ContextMenu  >
                <ContextMenu>
                    <MenuItem Header="Delete" Command="{Binding OpenDialogCommand}"  CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"></MenuItem>
                </ContextMenu>
            </DataGrid.ContextMenu>

            <DataGrid.Columns>
                <DataGridTextColumn Header="Priority" Width="auto" Binding="{Binding Path=Id}"/>
                
                <DataGridTextColumn Header="Task" Width="auto" Binding="{Binding Path=TaskName}"/>              
            </DataGrid.Columns>

           
        </DataGrid>
Soumya
  • 323
  • 1
  • 5
  • 16
  • https://stackoverflow.com/questions/5200687/create-contextmenus-for-datagrid-rows – ASh Jan 04 '23 at 14:24

4 Answers4

0

You could set the ContextMenu property conditionally using a Style with a Trigger:

<DataGrid ItemsSource="{Binding Path=TaskList}" SelectedItem="{Binding SelectedTask}" AutoGenerateColumns="False">
    <DataGrid.Style>
        <Style TargetType="DataGrid">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem Header="Delete" Command="{Binding OpenDialogCommand}"  
                                      CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"></MenuItem>
                    </ContextMenu>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="HasItems" Value="False">
                    <Setter Property="ContextMenu" Value="{x:Null}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.Style>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Priority" Width="auto" Binding="{Binding Path=Id}"/>
        <DataGridTextColumn Header="Task" Width="auto" Binding="{Binding Path=TaskName}"/>
    </DataGrid.Columns>
</DataGrid>
mm8
  • 163,881
  • 10
  • 57
  • 88
0

You could bind visibility and use the built in booleantovisibility converter

You need the converter. This could be in a resource dictionary you merge in app.xaml to use across the app.

  <Window.Resources>
    <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/>
  </Window.Resources>

Then just bind visibility on the context menu

<DataGrid ...... >
    <DataGrid.ContextMenu>
        <ContextMenu Visibility="{Binding PlacementTarget.HasItems, RelativeSource={RelativeSource Self}, 
                                  Converter={StaticResource booleanToVisibilityConverter}}">
             <MenuItem Header="Delete" 
                       Command="{Binding OpenDialogCommand}"  
                       CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
        </ContextMenu>
    </DataGrid.ContextMenu>
Andy
  • 11,864
  • 2
  • 17
  • 20
0

As one of variations, you can use ContextMenuService.IsEnabled attached property and bind it with ItemsControl.HasItems.

<DataGrid ...
          ContextMenuService.IsEnabled="{Binding RelativeSource={RelativeSource Self}, Path=HasItems}">
emoacht
  • 2,764
  • 1
  • 13
  • 24
0

I got a simple hack to solve this. I changed the row definition from * to auto for row 2; This will stop context menu from showing when you click anywhere other than Datagrid Elements.

<RowDefinition Height="auto"/>

Also to remove one extra row which always shows(and display context menu when right clicked)

This worked.

    <DataGrid Margin ="10" x:Name="dgTaks" Grid.Row="1" Grid.ColumnSpan="2"  ItemsSource="{Binding Path=TaskList}" SelectedItem="{Binding SelectedTask}" AutoGenerateColumns="False" **CanUserAddRows="False"**>
Soumya
  • 323
  • 1
  • 5
  • 16