我正在尝试使用MVVM在WPF 4.0中创建一个DataGrid ...
所需功能-
像这样-
已经两天了,我无法弄清楚如何有效地解决问题。
一个有效的例子是我现在需要的尽快。
如果有人可以与我分享工作解决方案,我将不胜感激。
N请不要告诉我用Google来搜索这个东西,因为没有一个适合我。
更新-
首先,“全选”功能,即选中复选框,单击列标题中存在的所有复选框...(我可以选择和取消选择数据网格,但不能选中/取消选中复选框)
其次,在不按住Ctrl键的情况下单击鼠标的多项选择。
最佳答案
当您使用MVVM时,您必须知道什么被视为数据以及什么是严格的UI。
您的SelectedItems
将成为数据的一部分,还是仅成为UI的一部分?
如果它是数据的一部分,则实际上应该在数据模型上具有IsSelected
属性,即使这意味着扩展数据类以包括IsSelected
属性,或创建仅包含bool IsSelected
和object 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
并使用后面的一些代码来确保CheckBox
与SelectedItem
正确同步。我做了一个快速的示例应用程序,这是我的代码的样子:
首先,我只是使用
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
选择事件。这样可以确保仅当您单击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
中设置绑定(bind)值,而不是在CheckBox.IsChecked
中设置DataGrid.Rows
),或者可以作为Adolfo Perez suggested并将其绑定(bind)到ViewModel
上的属性。关于wpf - 带有DataGrid WPF的复选框,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17114603/