2

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...

juarola
  • 689
  • 2
  • 10
  • 20

1 Answers1

1

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

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • ViewModel-classes are derived from MVVMLight-framework's ViewModelBase, which implement INPC. – juarola Apr 17 '11 at 15:40
  • Ok, then try raising property change event for IsSelected property. – Rohit Vats Apr 17 '11 at 15:42
  • Hmm, i'm starting to see the problem. IsSelected-property is not within the ViewModel, but in the Model, which is a poco. How should i refactor the code to have row-specific IsSelected-properties within the ViewModel? Edit: Should i create a separate ViewModel to contain an individual row? – juarola Apr 17 '11 at 15:44
  • That did it. One of the "feeling stupid"-situations here, i really don't know why i didn't implement this part of the app just like the others :-) Thanks! – juarola Apr 17 '11 at 15:51
  • Any chance you can provide your updated solution and mark it as the answer for all to see? Thx! – KyleLib May 06 '11 at 19:00