Reputation: 2192
I have a ListBox which has an itemcontainerstyle, it has background color(lets say Green) too in this style, I want to change the background color from MVVM. The color will change on some specific condition,otherwise the default color(ie Green) should apply.
<ListBox x:Name="lst1" ItemsSource="{Binding DataSource}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" Style="{DynamicResource StepListBox}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}" Margin="-10,0,0,0">
//Listbox Items
</ListBox>
and this is my ListboxItemStyle,its defined in a separate xaml file
<Style x:Key="ListboxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Margin" Value="20,0,0,10"/>
<Setter Property="Background" Value="{DynamicResource Green}"/>
<Setter Property="BorderBrush" Value="{DynamicResource TertiaryMediumStroke}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource SecondaryDark}"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="10,10,0,10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<Grid Margin="0">
<Rectangle x:Name="BgColor" Fill="{DynamicResource TertiaryMediumStroke}" Margin="-10,-10,0,-10" Opacity="0.1"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<!--#FFD1EFD6-->
<Setter Property="Background" TargetName="Bd" Value="#FFD7F0DB" />
<Setter Property="Opacity" TargetName="BgColor" Value="0" />
<Setter Property="Foreground" Value="{DynamicResource ForeLight}"/>
</Trigger>
<!--
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>
-->
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="BgColor" Value="0" />
<Setter Property="Foreground" Value="{DynamicResource ForeDisable}"/>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource TertiaryMedium}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I change this in my ViewModel?
Upvotes: 0
Views: 732
Reputation: 69959
When using MVVM, the view models should really know nothing about the views. However, if you really insist on changing UI element colours from the view model, then you can follow this approach. The idea is to have one or more properties with primitive types, such as bool
, int
, or even enum
, that are data bound in the UI. Using DataTrigger
s, your UI can 'listen' for changes in these properties and update colours accordingly. Take this example:
If you have just one or two colours to update, you can use a bool
property and a some DataTrigger
s:
<Style>
<Setter Property="Background" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsElementRed}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
If you have a range of colours to update, you could use a custom enum
:
<Style>
<Setter Property="Background" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding EnumInstance}" Value="SomeValue">
<Setter Property="Background" Value="Red" />
</DataTrigger>
...
<DataTrigger Binding="{Binding EnumInstance}" Value="SomeOtherValue">
<Setter Property="Background" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
Alternatively, you could also use an IValueConverter
to convert between the enum
instance and the various required colours.
Upvotes: 1
Reputation: 2521
You'll only need a DataTrigger in your Style on a boolean in your ViewModel layer:
<Style.Triggers>
<DataTrigger Binding="{Binding MyBooleanProperty, Mode=OneWay}" Value="True">
<Setter Property="Background" Value="WhatEverColorYouWant"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="Background" Value="Green"/>
And in your ViewModel:
public bool MyBool {
get { return _firstCondition && _secondCondition && _thirdCondition; }
}
And when one of the condition changes, you'll just want to raise a NotifyPropertyChanged on MyBool
Upvotes: 0