1
votes

I have a WPF application with a DataGrid and I want the user be able to doubleclick on a row to open up an edit dialog.

So I added a SelectedItem property in my ViewModel and InputBinding to my Grid. Now I have a command in my ViewModel which is fired when the user doubleclicks on the grid. I get the correct selected item too. So far so good.

The problem is, the event gets also fired when the user clicks on some empty space on the grid (I marked it on the picture)..

on the marked places user should not be able to doubleclick

The user should not be able to perform a double click action on the empty spaces. Because the event gets fired with the SelectedItem not changed. So this is wrong.

My XAML code for the DataGrid:

<DataGrid Name="dgSafetyFunction" AutoGenerateColumns="False" ItemsSource="{Binding SafetyFunctionList}" Margin="0,0,0,45" 
              SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" IsReadOnly="True" IsSynchronizedWithCurrentItem="True" SelectionUnit="FullRow">
    <DataGrid.InputBindings>
        <MouseBinding
            MouseAction="LeftDoubleClick"
            Command="{Binding OnDataGridDoubleClickCommand}"/>
    </DataGrid.InputBindings>
    <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Beschreibung" Binding="{Binding Description}"/>
        <DataGridTextColumn Header="Projekt ID" Binding="{Binding ProjectID}"/>
    </DataGrid.Columns>
</DataGrid>

The SelectedItem property:

private SafetyFunctionModel m_SelectedItem;

public SafetyFunctionModel SelectedItem
{
    get
    {
        return m_SelectedItem;
    }
    set
    {
        if (value != m_SelectedItem)
        {
            m_SelectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }
}

How can I fix this the MVVM way?

Regards

2

2 Answers

2
votes

Define a CellTemplate and move the MouseBinding to the root element of this one:

<DataGrid Name="dgSafetyFunction" AutoGenerateColumns="False" ItemsSource="{Binding SafetyFunctionList}" Margin="0,0,0,45" 
          SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" IsReadOnly="True" IsSynchronizedWithCurrentItem="True" SelectionUnit="FullRow">
    <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Beschreibung" Binding="{Binding Description}"/>
        <DataGridTextColumn Header="Projekt ID" Binding="{Binding ProjectID}"/>
    </DataGrid.Columns>
    <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            <Border.InputBindings>
                                <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding DataContext.OnDataGridDoubleClickCommand, 
                                            RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                            </Border.InputBindings>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                </Trigger>
                <Trigger Property="IsKeyboardFocusWithin" Value="True">
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/>
                </Trigger>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsSelected" Value="true"/>
                        <Condition Property="Selector.IsSelectionActive" Value="false"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                </MultiTrigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>
2
votes

You can set the event for DataGridRow, something like this

<DataGrid.Resources>
    <Style TargetType="DataGridRow">
        <Setter Property="command:CommandBehavior.Event" Value="MouseDoubleClick"/>
        <Setter Property="command:CommandBehavior.Command" Value="{Binding DataContext.MouseDoubleClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}"/>
    </Style>
</DataGrid.Resources>