I have a listbox like this:
<ListBox ItemsSource="{Binding Users}" SelectedItem="{Binding CurrentSelectedUser}"
DisplayMemberPath="Username"/>
Users is a Observable collection of User
which is a class with 2 properties which is Username
and Password
.
I then have a property called CurrentUser
on my view model. What I want to do is change the colour of the listboxs item if the Text on it is equal to CurrentUser.Username
. Here is what I have tried so far:
<ListBox ItemsSource="{Binding Users}" SelectedItem="{Binding CurrentSelectedUser}"
DisplayMemberPath="Username">
<ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Content.Username}" Value="{Binding CurrentUser.Username}">
<Setter Property="Background" Value="Green"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
This doesn't work. Is there any way to do this? I know that Value
is not a dependency property. But I want to do something like this.
It's not compiling because value is not a dependency property, said that you cannot use binding in a non dependency property.
You can use IMultiValueConverter to return the color according with the parameter received, here's an example.
Converter:
public class Converter : IMultiValueConverter
{
public Converter()
{
}
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var currentPersonName = values[0].ToString();
var listItemPersonName = values[1].ToString();
return currentPersonName == listItemPersonName ? Brushes.Red : Brushes.Black;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Here you will receive the two names by parameter, so you can compare and return the color you want.
You pass these two values by Multibinding, here's the XAML.
XAML:
<Window.Resources>
<local:Converter x:Key="converter"/>
<Style x:Key="style" TargetType="ListBoxItem">
<Setter Property="Foreground">
<Setter.Value>
<MultiBinding Converter="{StaticResource converter}">
<MultiBinding.Bindings>
<Binding Path="DataContext.CurrentPerson.UserName"
RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
<Binding Path="UserName"/>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ListBox ItemsSource="{Binding Persons}"
DisplayMemberPath="{Binding UserName}"
ItemContainerStyle="{StaticResource style}"
SelectedItem="{Binding SelectedPerson}">
</ListBox>
I did a style just like you did, but instead use DataTrigger I used a Multibinding to pass the values to be compared to the converter.
In the first binding I retrieve the userName of the current person in my viewModel, to do this I need specify where is the object, this is the reason of relativeSource.
In the second binding, I just get the Property UserName directly of the ListItemBox DataContext, which has an object of type Person bind to it.
And that is it, it works like expected.