1

Change the ListBoxItem color to the property on ViewModel

 3 years ago
source link: https://www.codesd.com/item/change-the-listboxitem-color-to-the-property-on-viewmodel.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Change the ListBoxItem color to the property on ViewModel

advertisements

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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK