带有DataGrid WPF的复选框

带有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”或任何此类属性 我只面临两个问题- 首先,“全选”功能,即选中列标

我正在尝试使用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>