我正在尝试使用MVVM在WPF 4.0中创建一个DataGrid ...

所需功能-

  • Muti-使用复选框(单击一下)选择行
  • A选择所有复选框以检查datagrid
  • 中的所有复选框

    像这样-

    已经两天了,我无法弄清楚如何有效地解决问题。

    一个有效的例子是我现在需要的尽快。

    如果有人可以与我分享工作解决方案,我将不胜感激。

    N请不要告诉我用Google来搜索这个东西,因为没有一个适合我。

    更新-
  • 我正在使用列自动生成
  • 我不想在我的MODEL中添加“IsSelected”或任何此类属性。
  • 我正面临2个问题-

  • 首先,“全选”功能,即选中复选框,单击列标题中存在的所有复选框...(我可以选择和取消选择数据网格,但不能选中/取消选中复选框)

    其次,在不按住Ctrl键的情况下单击鼠标的多项选择。

    最佳答案

    当您使用MVVM时,您必须知道什么被视为数据以及什么是严格的UI。

    您的SelectedItems将成为数据的一部分,还是仅成为UI的一部分?

    如果它是数据的一部分,则实际上应该在数据模型上具有IsSelected属性,即使这意味着扩展数据类以包括IsSelected属性,或创建仅包含bool IsSelectedobject MyDataItem的包装器类。第一个选项可能是首选,因为您可以保留AutoGenerateColumns="True",它使列绑定(bind)更简单。

    然后,您只需将DataGridRow.SelectedItem绑定(bind)到数据项的IsSelected属性即可:

    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="IsSelected" Value="{Binding IsSelected}" />
    </Style>
    

    但是,如果您的SelectedItems仅用于UI,或者在这种情况下由于某种原因而中断了MVVM模式,那么您可以创建未绑定(bind)的CheckBox并使用后面的一些代码来确保CheckBoxSelectedItem正确同步。

    我做了一个快速的示例应用程序,这是我的代码的样子:

    首先,我只是使用CheckBox将未绑定(bind)的DataGridTemplateColumn列添加到列列表中。这将被添加到列的AutoGenerateColumns列表之前。
    <DataGrid x:Name="TestDataGrid" ItemsSource="{Binding Test}"
              SelectionMode="Extended" CanUserAddRows="False"
              PreviewMouseLeftButtonDown="TestDataGrid_PreviewMouseLeftButtonDown_1">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox x:Name="TestCheckBox"
                                  PreviewMouseLeftButtonDown="CheckBox_PreviewMouseLeftButtonDown" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    

    其次,我在PreviewMouseDown中添加了CheckBox事件,以使其设置行的IsSelected属性。

    private void CheckBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var chk = (CheckBox)sender;
        var row = VisualTreeHelpers.FindAncestor<DataGridRow>(chk);
        var newValue = !chk.IsChecked.GetValueOrDefault();
    
        row.IsSelected = newValue;
        chk.IsChecked = newValue;
    
        // Mark event as handled so that the default
        // DataGridPreviewMouseDown doesn't handle the event
        e.Handled = true;
    }
    

    它需要导航VisualTree来找到与单击的DataGridRow关联的CheckBox才能选择它,并且为了使生活更轻松,我正在使用一些自定义VisualTreeHelpers that I have on my blog来查找DataGridRow。您可以使用相同的代码,也可以创建自己的搜索VisualTree的方法。

    最后,如果用户单击CheckBox以外的任何其他位置,我们想禁用默认的DataGrid选择事件。这样可以确保仅当您单击IsSelectedCheckBox值才会更改。

    有多种方法可以在不同级别上禁用选择,但是为了简化生活,如果用户未单击DataGrid.PreviewMouseLeftButtonDown,我就禁用了CheckBox事件。

    private void TestDataGrid_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
    {
        var chk = VisualTreeHelpers.FindAncestor<CheckBox>((DependencyObject)e.OriginalSource, "TestCheckBox");
    
        if (chk == null)
            e.Handled = true;
    }
    

    我再次使用自定义的VisualTreeHelpers导航可视化树,找出是否单击了CheckBox,如果用户单击了CheckBox以外的其他位置,则取消该事件。

    至于您向CheckBoxSelectAll项目添加UnselectAll的第二个请求,这再次取决于您的选择是UI还是数据的一部分。

    如果它是UI的一部分,只需将CheckBox添加到DataGridTemplateColumn.HeaderTemplate,然后单击它,循环遍历DataGrid.Rows,在第一列中找到CheckBox,然后选中或取消选中它。

    如果它是数据的一部分,您仍然可以做同样的事情(仅在DataGrid.Items中设置绑定(bind)值,而不是在CheckBox.IsChecked中设置DataGrid.Rows),或者可以作为Adolfo Perez suggested并将其绑定(bind)到ViewModel上的属性。

    关于wpf - 带有DataGrid WPF的复选框,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17114603/

    10-15 16:34