带有DataGrid WPF的复选框
我正在尝试使用MVVM在WPF4.0中创建DataGrid 所需功能-带有DataGrid WPF的复选框,wpf,mvvm,wpf-controls,wpfdatagrid,wpf-4.0,Wpf,Mvvm,Wpf Controls,Wpfdatagrid,Wpf 4.0,我正在尝试使用MVVM在WPF4.0中创建DataGrid 所需功能- 多-使用复选框选择行(单击一次) 选中所有复选框以选中datagrid中的所有复选框 像这样的- 已经两天了,我无法想出如何有效地解决这个问题 一个有效的例子就是我现在需要尽快 如果有人有一个有效的解决方案与我分享,我将不胜感激 N请不要告诉我用谷歌搜索这件事,因为没有一件事适合我 更新- 我正在使用自动生成列 我不想在我的模型中添加“IsSelected”或任何此类属性 我只面临两个问题- 首先,“全选”功能,即选中列标
第二,在不按住Ctrl键的情况下单击鼠标进行多项选择 对于MVVM解决方案,您可以尝试以下方法:
<StackPanel>
<DataGrid ItemsSource="{Binding Path=TestItems}" AutoGenerateColumns="False" Name="MyDataGrid"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsSelected}" Width="50" >
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate x:Name="dtAllChkBx">
<CheckBox Name="cbxAll" Content="All" IsChecked="{Binding Path=DataContext.AllSelected,RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGridTemplateColumn Header="Name" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
最后是示例模型类:
public class TestItem : ModelBase<TestItem>
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
NotifyPropertyChanged(m => m.Name);
}
}
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set
{
_IsSelected = value;
NotifyPropertyChanged(m => m.IsSelected);
}
}
}
公共类测试项:ModelBase
{
私有字符串\u名称;
公共字符串名
{
获取{return\u Name;}
设置
{
_名称=值;
NotifyPropertyChanged(m=>m.Name);
}
}
私立学校当选;
公选学校
{
获取{return}IsSelected;}
设置
{
_IsSelected=值;
NotifyPropertyChanged(m=>m.IsSelected);
}
}
}
上面的大部分代码都应该是不言自明的,但是如果您有任何问题,请告诉我
<DataGrid Name="SomeDataGrid" Grid.Row="0" ItemsSource="{Binding Path=SomeCollection}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.AllItemsAreChecked}" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:SomeType}">
<CheckBox Focusable="False" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="RandomNumber" Width="160">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:SomeType}">
<TextBlock Text="{Binding Path=RandomNumber}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Date" Width="160">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:SomeType}">
<TextBlock Text="{Binding Path=Date}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Time" Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:SomeType}">
<TextBlock Text="{Binding Time}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
和在viewmodel中
SomeCollection绑定属性是observablecollection
sometype包含IsSelected、RandomNumber、Date和Time等属性
例如:
class ViewModel
{
public ObservableCollection<SomeType> SomeCollection{get;set;}
}
class SomeType
{
public string Date {get;set;}
public string Time {get;set;}
public string RandomNumber {get;set;}
public bool IsSelected {get;set;}
}
类视图模型
{
public observeCollection SomeCollection{get;set;}
}
类SomeType
{
公共字符串日期{get;set;}
公共字符串时间{get;set;}
公共字符串随机数{get;set;}
公共布尔值被选为{get;set;}
}
当您使用MVVM时,您必须知道什么是数据,什么是严格意义上的UI
您的SelectedItems
将成为您的数据的一部分,还是只是您的UI
如果它是数据的一部分,那么在数据模型上确实应该有一个IsSelected
属性,即使这意味着扩展数据类以包含IsSelected
属性,或者创建一个只包含bool IsSelected
和对象MyDataItem
的包装类。第一个选项可能是首选选项,因为您可以保留AutoGenerateColumns=“True”
,并且它使列绑定更简单
然后您只需将您的DataGridRow绑定到数据项的IsSelected
属性:
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
其次,我在复选框中添加了一个PreviewMouseDown
事件,使其设置行的IsSelected
属性
private void复选框\u PreviewMouseLeftButtonDown(对象发送器,鼠标按钮ventargs e)
{
var chk=(复选框)发送方;
var row=VisualTreeHelpers.FindAncestor(chk);
var newValue=!chk.IsChecked.getValuerDefault();
row.IsSelected=newValue;
chk.IsChecked=新值;
//将事件标记为已处理,以便默认
//DataGridPreviewMouseDown不处理该事件
e、 已处理=正确;
}
它需要浏览VisualTree
以找到与单击的复选框相关联的DataGridRow
,然后选择它,并且为了让生活更轻松,我正在使用一些自定义来查找DataGridRow
。您可以使用相同的代码,也可以创建自己的方法来搜索VisualTree
最后,如果用户单击复选框以外的任何位置,我们希望禁用默认的DataGrid
选择事件。这确保了IsSelected
值仅在单击复选框时才会更改
有多种方法可以在不同级别禁用选择,但为了简化操作,我只禁用了DataGrid.PreviewMouseLeftButtonDown
事件,如果用户没有单击复选框
private void TestDataGrid\u PreviewMouseLeftButtonDown\u 1(对象发送器,鼠标按钮ventargs e)
{
var chk=visualtreehelopers.FindAncestor((DependencyObject)e.OriginalSource,“TestCheckBox”);
如果(chk==null)
e、 已处理=正确;
}
我再次使用“我的自定义”导航可视化树,并查看是否单击了复选框,如果用户单击了除复选框以外的任何位置,则取消事件
至于您第二次请求将复选框添加到SelectAll
或UnselectAll
项目,这将再次取决于您的选择是否是UI或数据的一部分
如果它是UI的一部分,只需添加一个
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
<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>