I'm making a MVVM WPF application, in this application I have a ListBox with my own Privilege Items.
After ages I finally found a solution how to get selection synchronized with my ViewModel. (You also need to implement IEquatable in your item class)
Problem
Now i want to style the ListBoxItems as CheckBoxes, there are many solutions for this problem, but none that really fits my needs.
So i came up with this solution, because I can apply this style only to the ListBoxes I need, and I don't have to worry about the DisplayMemberPath or that the Items were styled as CheckBox and ListBoxItems.
View:
<ListBox Grid.Row="5" Grid.Column="1"
ItemsSource="{Binding Privileges}"
BehavExt:SelectedItems.Items="{Binding SelectedPrivileges}"
SelectionMode="Multiple"
DisplayMemberPath="Name"
Style="{StaticResource CheckBoxListBox}"/>
Style:
<Style x:Key="CheckBoxListBox"
TargetType="{x:Type ListBox}"
BasedOn="{StaticResource MetroListBox}">
<Setter Property="Margin" Value="5" />
<Setter Property="ItemContainerStyle"
Value="{DynamicResource CheckBoxListBoxItem}" />
</Style>
<Style x:Key="CheckBoxListBoxItem"
TargetType="{x:Type ListBoxItem}"
BasedOn="{StaticResource MetroListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<CheckBox IsChecked="{TemplateBinding Property=IsSelected}">
<ContentPresenter />
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ViewModel:
private ObservableCollection<Privilege> _privileges;
public ObservableCollection<Privilege> Privileges
{
get { return _privileges; }
set {
_privileges = value;
RaisePropertyChanged(() => Privileges);
}
}
private ObservableCollection<Privilege> _selectedPrivileges;
public ObservableCollection<Privilege> SelectedPrivileges
{
get { return _selectedPrivileges; }
set
{
_selectedPrivileges = value;
RaisePropertyChanged(() => SelectedPrivileges);
}
}
The Problem is this line:
IsChecked="{TemplateBinding Property=IsSelected}"
It works fine, but only in one direction. When add a item to my SelectedPrivileges
in the code it will be displayed as checked, but when I check this item in the GUI it won't do anything. (Without the CheckBox style it works, so it is because a TemplateBinding only works in one direction)
How do I get this to work? I though about something like a trigger, but I have no clue how to accomplish this.
I believe what you're looking for is actually pretty straightforward. You need to change the binding mode of the
IsChecked
property's binding, as follows:That should do it.
This and basically any other WPF binding tips can be found on this excellent cheat sheet.