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...
If you have derived ReportListItemModel
from INotifyPropertyChanged then raise property changed event from IsSelected
property setter: RaisePropertyChange("IsSelected")
.