Reputation: 854
I am still wrapping my head around this whole MVVM pattern but i thought i had a good grasp on it until i attempted to create a Checkbox column for my Gridview. I need the user to be able to select all items listed(via the header checkbox) or select the items listed individually. I databound the IsChecked property of my checkboxes to two boolean fields on my viewmodel. The checkbox on the cell template works as expected and fires the property changed event. The header does nothing. What am i missing here. Again this is still new to me so be gentle. Also if there is something i should be doing, or a better way to accomplish this...im all ears.
Thanks
XAML
<UserControl x:Class="CheckBoxDemo.GridDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ListView ItemsSource="{Binding PersonList}">
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsMainSelected}"/>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="100"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
ViewModel
class GridDemoViewModel:INotifyPropertyChanged
{
public List<Person> PersonList { get; private set; }
// Fields...
private bool _isMainSelected;
public bool IsMainSelected
{
get { return _isMainSelected; }
set
{
_isMainSelected = value;
NotifyPropertyChanged("IsMainSelected");
}
}
public GridDemoViewModel()
{
PersonList = new List<Person>();
PersonList.Add(new Person { Name = "John"});
PersonList.Add(new Person { Name = "Tom" });
PersonList.Add(new Person { Name = "Tina" });
PersonList.Add(new Person { Name = "Mary" });
PersonList.Add(new Person { Name = "Mia"});
PersonList.Add(new Person { Name = "Crystal" });
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Person Class
public class Person:INotifyPropertyChanged
{
public string Name { get; set; }
// Fields...
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected == value)
return;
_isSelected = value;
NotifyPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Upvotes: 1
Views: 10104
Reputation: 8503
The issue is that the GridViewColumn is not part of the Visual Tree. This means that it does not inherit the DataContext of the parent ListView. You have to find some other way of referencing the ViewModel. Check out Josh Smith's DataContextSpy which allows you to easily introduce an "artificially inherited" DataContext
<UserControl.Resources>
<spy:DataContextSpy x:Key="Spy" />
</UserControl.Resources>
<DataTemplate>
<CheckBox IsChecked="{Binding Source={StaticResource Spy} Path=DataContext.IsMainSelected}"/>
</DataTemplate>
Upvotes: 2