当你使用 MVVM 时,你必须知道什么是数据,什么是严格的 UI。
您SelectedItems将成为数据的一部分,还是只是您的 UI?
如果它是您数据的一部分,那么您确实应该IsSelected在数据模型上拥有一个属性,即使这意味着扩展数据类以包含一个属性,或者创建一个仅包含andIsSelected的包装类。第一个选项可能是首选,因为您可以保留,它使列绑定更简单。bool IsSelectedobject MyDataItemAutoGenerateColumns="True"
然后,您只需将您的绑定DataGridRow.SelectedItem到IsSelected数据项的属性:
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
但是,如果您SelectedItems仅用于 UI,或者您在这种情况下由于某种原因破坏了 MVVM 模式,那么您可以创建未绑定CheckBox并使用一些代码来确保CheckBox正确同步到SelectedItem.
我做了一个快速示例应用程序,我的代码如下所示:
首先,我只是CheckBox使用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 来查找DataGridRow. 您可以使用相同的代码,也可以创建自己的方法来搜索VisualTree.
最后,如果用户点击 以外的任何地方CheckBox,我们希望禁用默认DataGrid选择事件。这确保了该IsSelected值仅在您单击 时才会更改CheckBox。
有多种方法可以禁用不同级别的选择,但为了简单起见,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.
至于您添加CheckBox到SelectAll或UnselectAll项目的第二个请求,这将再次取决于您的选择是 UI 还是数据的一部分。
如果它是 UI 的一部分,只需在 中添加一个CheckBox,DataGridTemplateColumn.HeaderTemplate然后单击它时,循环浏览,在第一列中DataGrid.Rows找到,然后选中或取消选中它。CheckBox
如果它是数据的一部分,您仍然可以做同样的事情(仅在 中设置绑定值DataGrid.Items而不是CheckBox.IsCheckedfrom DataGrid.Rows),或者您可以按照Adolfo Perez 的建议进行操作,并将其绑定到ViewModel.