如何在DataGrid中检测是否单击了行并将其列从true更改为false,反之亦然?

时间:2018-10-02 07:27:13

标签: c# wpf xaml datagrid selectionchanged

我正在开发一个小型WPF应用程序,当我单击一行时,我将我的复选框列选中/未选中。这是我的行的样子:

enter image description here

这是我的代码:

private void dtgTest_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (dtgTest.SelectedItem != null)
    {
        CheckBox checkbocColumn = (dtgTest.Columns[3].GetCellContent(dtgTest.SelectedItem) as CheckBox);
        checkbocColumn.IsChecked = !checkbocColumn.IsChecked;


        var selectedItem = (BillItemInSerie)dtgTest.SelectedItem;
        var obj = serialNumbersIn.FirstOrDefault(sn => selectedItem.DocumentItemInSeriesId == sn.DocumentItemInSeriesId);
        obj.IsChecked= (bool)checkbocColumn.IsChecked;

    }
}

这是我填充DataGrid的方式:

public Test_Window()
   : this()
{
    databaseValues = Controller.Instance.GetById(Id);
    dtgTest.ItemsSource = null;
    dtgTest.ItemsSource = databaseValues;
}

所以当生成表单时,我准确地从数据库中获取了所有项目

这是我的XAML:

<DataGrid Name="dtgTest"  IsReadOnly="True"  VirtualizingStackPanel.VirtualizationMode="Standard"  EnableColumnVirtualization = "True" EnableRowVirtualization ="True"  MaxWidth="4000" MaxHeight="2000" Background="White" Margin="5,5,5,0" AutoGenerateColumns="False" RowHeaderWidth="0"  HorizontalGridLinesBrush="#0091EA" VerticalGridLinesBrush="#0091EA" CanUserAddRows="False" RowHeight="30" Grid.ColumnSpan="2" Grid.Row="2" SelectionChanged="dtgTest_SelectionChanged">
    <DataGrid.CellStyle>
        <StaticResource ResourceKey="DataGridCentering"/>
    </DataGrid.CellStyle>
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="Background" Value="#0091EA"/>
            <Setter Property="Opacity" Value="1"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="FontSize" Value="{x:Static local:Globals.dataGridfontSizeHeader}"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="Height" Value="40"/>
        </Style>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
           Color="LightBlue"/>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn         Binding="{Binding Value1}"          Header=""   Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*"  />
        <DataGridTextColumn         Binding="{Binding Value2}"          Header=""   Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*"   />
        <DataGridTextColumn         x:Name="colFormatedDate"            Binding="{Binding ExpireDate, StringFormat ={}{0:MM/yyyy}}"     Header=""   Foreground="Black"      FontSize="15" FontFamily="Verdana" Width="20*" />
        <DataGridCheckBoxColumn     x:Name="colSelektiraj"              Binding="{Binding IsChecked}"       Header=""  Width="10*" />
    </DataGrid.Columns>
</DataGrid>

但是,当我单击一行并选中复选框列(像上面的示例图像)时,问题就出现了;如果我立即改变主意,然后再次单击选中的行以更改状态,问题就出在这里。复选框列之所以无法执行,因为dtgTest_SelectionChanged不会触发,因为我没有更改选择。.

因此,我想检测是否单击了行可能对我有帮助?因此,我可能会执行与dtgTest_SelectionChanged事件中类似的代码?

任何一种帮助都会很棒! 谢谢,伙计们

欢呼

在Rekshino帮助之后进行编辑:

<DataGrid Name="dtgTest" IsReadOnly="True"  VirtualizingStackPanel.VirtualizationMode="Standard"  EnableColumnVirtualization = "True" EnableRowVirtualization ="True"  MaxWidth="4000" MaxHeight="2000" Background="White" Margin="5,5,5,0" AutoGenerateColumns="False" RowHeaderWidth="0"  HorizontalGridLinesBrush="#0091EA" VerticalGridLinesBrush="#0091EA" CanUserAddRows="False" RowHeight="30" Grid.ColumnSpan="2" Grid.Row="2" SelectionChanged="dtgTest_SelectionChanged" PreviewMouseDown="dtgTest_PreviewMouseDown">
    <DataGrid.CellStyle>
        <StaticResource ResourceKey="DataGridCentering"/>
    </DataGrid.CellStyle>
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="Background" Value="#0091EA"/>
            <Setter Property="Opacity" Value="1"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="FontSize" Value="{x:Static local:Globals.dataGridfontSizeHeader}"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="Height" Value="40"/>
        </Style>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue"/>
        <Style TargetType="DataGridCell">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="dtgTest_PreviewMouseDown"/>
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn         Binding="{Binding Value1}"          Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*"  />
        <DataGridTextColumn         Binding="{Binding Value2}"          Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*"   />
        <DataGridTextColumn         x:Name="colFormatedDate"            Binding="{Binding ExpireDate, StringFormat ={}{0:MM/yyyy}}"   Foreground="Black"      FontSize="15" FontFamily="Verdana" Width="20*" />
        <DataGridCheckBoxColumn     x:Name="colSelektiraj"              Binding="{Binding IsChecked, NotifyOnTargetUpdated=True}"     Header=""  Width="10*" />
    </DataGrid.Columns>
</DataGrid>

C#:

private void dtgTest_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{

    var cell = sender as DataGridCell;

    if (cell == null)
    {
        return;
    }

    DataGridRow parGridRow = null;
    var visParent = VisualTreeHelper.GetParent(cell);
    while (parGridRow == null && visParent != null)
    {
        parGridRow = visParent as DataGridRow;
        visParent = VisualTreeHelper.GetParent(visParent);
    }
    if (parGridRow == null) { return; }

    var selectedItem = (parGridRow.DataContext as BillItemInSerie);
    var obj = serialNumbersIn.FirstOrDefault(sn => selectedItem.DocumentItemInSeriesId == sn.DocumentItemInSeriesId);
    obj.IsChecked = (bool)!obj.IsChecked;
}

3 个答案:

答案 0 :(得分:1)

您可以为单元格设置鼠标事件处理程序,获取行并使用它进行所需的操作。我已删除了SelectionChanged的事件处理程序,因为在此解决方案中不需要它。

<DataGrid Name="dtgTest"  IsReadOnly="True"  VirtualizingStackPanel.VirtualizationMode="Standard"  EnableColumnVirtualization = "True" EnableRowVirtualization ="True"  MaxWidth="4000" MaxHeight="2000" Background="White" Margin="5,5,5,0" AutoGenerateColumns="False" RowHeaderWidth="0"  HorizontalGridLinesBrush="#0091EA" VerticalGridLinesBrush="#0091EA" CanUserAddRows="False" RowHeight="30" Grid.ColumnSpan="2" Grid.Row="2">
    <DataGrid.Resources>
        <Style TargetType="DataGridCell">
        <!-- If you have to apply another style, then use BasedOn-->
        <!--<Style TargetType="DataGridCell" BasedOn="{StaticResource DataGridCentering}">-->
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="PreviewMouseDown"/>
        </Style>
    </DataGrid.Resources>
    ...
</DataGrid>

private void PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var cell = sender as DataGridCell; if (cell == null) { return; }
    DataGridRow parGridRow = null;
    var visParent = VisualTreeHelper.GetParent(cell);
    while (parGridRow == null && visParent != null)
    {
        parGridRow = visParent as DataGridRow;
        visParent = VisualTreeHelper.GetParent(visParent);
    }
    if (parGridRow == null) { return; }
    var selectedItem = (parGridRow.DataContext as BillItemInSerie);
    var obj = serialNumbersIn.FirstOrDefault(sn => selectedItem.DocumentItemInSeriesId == sn.DocumentItemInSeriesId);
    obj.IsChecked= (bool)!obj.IsChecked;

    //e.Handled = true;
}

答案 1 :(得分:0)

如果您有一个ViewModel(MVVM),它代表每一行的数据。您应该/应该在其中具有表示CheckBox状态的bool属性(而不是从后面的代码中获取)。

接下来,您可以将DataGrid的SelectedItem绑定到对象(相关类型),并测试即使多次单击同一项目,该对象是否也会被触发。如果确实如此(至少在DevExpress gridControls中如此)-您应该在Setter中翻转SelectedItem的bool属性。

答案 2 :(得分:0)

嗨,您可以在复选框的绑定上设置一个标志。 目标(您的复选框)更改时,会触发一个NotifyOnTargetUpdated事件的TargetUpdated

在绑定上使用NotifyOnTargetUpdated=True可以激活它们。 您的DataGridCheckBoxColumn如下所示:

<DataGridCheckBoxColumn x:Name="colSelektiraj" Binding="{Binding IsChecked, NotifyOnTargetUpdated=True}" Header="" Width="10*" />

在Datagrid上,使用TargetUpdated="DataGrid_TargetUpdated"事件获得通知。您的数据网格如下所示:

<DataGrid Name="dtgTest" IsReadOnly="True" TargetUpdated="DataGrid_TargetUpdated" ...>

要在选择更改时得到通知,请像以前一样使用SelectionChanged事件。