使用 MVVM Light 的 WPF DataGrid TemplateColumn 带有复选框和全选复选框

发布于 2024-11-01 13:57:57 字数 3033 浏览 5 评论 0原文

我正在尝试创建一个带有一列复选框的 DataGrid。在该复选框列的标题上,我想要一个“选中/取消选中全部”类型的复选框。

应用程序正在使用 WPF、.NET 4 和 MVVM Light。

代码如下:

XAML:

<DataGrid x:Name="dgReportList" ItemsSource="{Binding Path=ReportListItems}">
<DataGrid.Columns>
    <DataGridTextColumn Header="*SomeText"  Binding="{Binding Path=SourceReport.Name}" />
    <DataGridTemplateColumn>
        <DataGridTemplateColumn.Header>
            <CheckBox IsChecked="{Binding Source={StaticResource Locator},     
                  Path=MainWindowViewModel.CheckAll, Mode=TwoWay, 
                  UpdateSourceTrigger=PropertyChanged}"  />
        </DataGridTemplateColumn.Header>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay, 
             UpdateSourceTrigger=PropertyChanged}">                                    
          </CheckBox>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
   </DataGridTemplateColumn>

...

ViewModel:

    private ObservableCollection<ReportListItemModel> _reportListItems;

    public ObservableCollection<ReportListItemModel> ReportListItems
    {
        get
        {
            return this._reportListItems;
        }
        private set
        {
            this._reportListItems = value;
            this.RaisePropertyChanged("ReportListItems");
        }
    }

    ....

    public bool CheckAll
    {
        get { return this._checkall; }
        set 
        {
            this._checkall = value; 

            foreach (var reportListItemModel in ReportListItems)
            {
                reportListItemModel.IsSelected = this._checkall;
            }
        }
    }

Model:

public class ReportListItemModel
{
    public EnvironmentConfigurationModel TargetConfigurationModel { get; set; }
    public ReportModel TargetReport { get; set; }

    public EnvironmentConfigurationModel SourceConfigurationModel { get; set; }
    public ReportModel SourceReport { get; set; }

    private bool _isSelected;

    public bool IsSelected
    {
        get { return _isSelected; }
        set 
        {
            _isSelected = value;
        }
    }
}

我的想法是将 DataGrid 绑定到 ReportListItemModel 类型的 ObservableCollection。 ReportListItemModel 包含一个公共布尔属性“IsSelected”,我想将其绑定到复选框。


场景:
作为用户,我希望能够通过单击位于标题行的复选框来选择(或取消选择)所有行。


测试:
任务:当“标题复选框”处于未选中状态时,单击“标题复选框”。
预期:各个行上的所有复选框都会被选中。
实际:仅选中标题行上的复选框。

任务:当“标题复选框”处于选中状态时,单击“标题复选框”。
预期:取消选中各行上的所有复选框。
实际:仅标题行上的复选框未被选中。


“全选”复选框和行上的复选框都会导致模型中的属性按预期设置。这只是不绑定到视图。我有一种令人毛骨悚然的感觉,我的模型和视图模型以某种方式设置得很有趣,即使 DataGridTextColumn 确实从模型 a-ok 中获取了值。

我很乐意提供所需的任何其他代码或信息!

注意,我刚刚开始使用 WPF、MVVM 等,所以如果这里存在一些基本缺陷,我会很高兴听到它。

编辑:
为了可读性进行了编辑...

i'm trying to create a DataGrid with a column of checkboxes. On that CheckBox-column's header, i'd like to have a "check/uncheck all"-type of checkbox.

App is using WPF, .NET 4 and MVVM Light.

Here's the code:

XAML:

<DataGrid x:Name="dgReportList" ItemsSource="{Binding Path=ReportListItems}">
<DataGrid.Columns>
    <DataGridTextColumn Header="*SomeText"  Binding="{Binding Path=SourceReport.Name}" />
    <DataGridTemplateColumn>
        <DataGridTemplateColumn.Header>
            <CheckBox IsChecked="{Binding Source={StaticResource Locator},     
                  Path=MainWindowViewModel.CheckAll, Mode=TwoWay, 
                  UpdateSourceTrigger=PropertyChanged}"  />
        </DataGridTemplateColumn.Header>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay, 
             UpdateSourceTrigger=PropertyChanged}">                                    
          </CheckBox>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
   </DataGridTemplateColumn>

...

ViewModel:

    private ObservableCollection<ReportListItemModel> _reportListItems;

    public ObservableCollection<ReportListItemModel> ReportListItems
    {
        get
        {
            return this._reportListItems;
        }
        private set
        {
            this._reportListItems = value;
            this.RaisePropertyChanged("ReportListItems");
        }
    }

    ....

    public bool CheckAll
    {
        get { return this._checkall; }
        set 
        {
            this._checkall = value; 

            foreach (var reportListItemModel in ReportListItems)
            {
                reportListItemModel.IsSelected = this._checkall;
            }
        }
    }

Model:

public class ReportListItemModel
{
    public EnvironmentConfigurationModel TargetConfigurationModel { get; set; }
    public ReportModel TargetReport { get; set; }

    public EnvironmentConfigurationModel SourceConfigurationModel { get; set; }
    public ReportModel SourceReport { get; set; }

    private bool _isSelected;

    public bool IsSelected
    {
        get { return _isSelected; }
        set 
        {
            _isSelected = value;
        }
    }
}

My idea is to bind the DataGrid to a ObservableCollection of type ReportListItemModel. ReportListItemModel contains a public boolean property "IsSelected", which i want to get bound to the checkbox.


Scenario:
As a user, i want to be able to select (or deselect) all the rows by clicking on the checkbox located at the header row.


Tests:
Task: Click the "Header-Checkbox", when it's state is unchecked.
Expected: All checkboxes on individual rows get checked.
Actual: Only the checkbox on header row gets checked.

Task: Click the "Header-Checkbox", when it's state is checked.
Expected: All checkboxes on individual rows get unchecked.
Actual: Only the checkbox on header row gets unchecked.


Both the "select all"-checkbox and the checboxes on the rows cause the property within model to be set as expected. This just doesn't get bound to the View. I have a creepy feeling that i have my model and viewmodel set funny somehow, even though the DataGridTextColumn does get the value from model a-ok.

I'm happy to provide any additional code or info required!

N.B. I'm just starting up with WPF, MVVM etc., so if there's some fundamental flaw here, i'd be happy to hear about it.

Edit:
Edited for readability...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↘紸啶 2024-11-08 13:57:57

如果您从 INotifyPropertyChanged 派生了 ReportListItemModel,则从 IsSelected 属性设置器引发属性更改事件: RaisePropertyChange( “已选择”)

If you have derived ReportListItemModel from INotifyPropertyChanged then raise property changed event from IsSelected property setter: RaisePropertyChange("IsSelected").

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文