In WPF is there some mechanisim to reuse the property setters amoung differant triggers? For example I have the following.
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter Property="Content" Value="Not Connected" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding IsConnected}" Value="False">
<Setter Property="Content" Value="Not Connected" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Content" Value="Connected" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
The setters for Null and False are identical and it would be nice if there was only a single point of change.
You can always create a resource like this:
<Setter x:Key="setter1" Property="Content" Value="Not Connected" />
However, you cannot use resource keys as object in a collection.
You could set somewhere
<SomeObject Setter="{StaticResource setter1}"/>
but Setters are almost always added to collections and you cannot add resource keys in xaml collection syntax.
The only scenario I can think of which would support this would be to create a SetterBaseCollection resource with those two identical pairs of Setters,
<SetterBaseCollection x:Key="settersKey">
<Setter Property="Label.Content" Value="Not Connected" />
<Setter Property="Label.Foreground" Value="Red" />
</SetterBaseCollection>
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}" Setters="{StaticResource settersKey}"/>
// ...
</Style.Triggers>
</Style>
but the DataTrigger.Setters collection property is readonly and cannot be set from xaml.
So, the answer would be no.
In this special case, it would be best to make the unconnected case the default (without a condition), and only create a DataTrigger for the one case that is different.
Related
This is the code i use but it is notworking
<Window.Resources>
<Style x:Key="PinkRow" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Rank}" Value="Master">
<Setter Property="Source" Value="A_Cancel.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding RANK}" Value="Bosun">
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding RANK}" Value="">
<Setter Property="Background" Value="yellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
If field rank has the value "Master" i want the image A_cancel.png
The C# is case sensitive, so the Rank and RANK are different properties. Use proper property name in your bindings. Also you must mention in your Setter the TargetName for Image element.
<DataTrigger Binding="{Binding Rank}" Value="Master">
<Setter TargetName="ImageElementName" Property="Source" Value="A_Cancel.png"/>
</DataTrigger>
I have the following DataTrigger in a WPF form:
<CheckBox IsChecked="{Binding ConcentratorViewModel.Integrated}">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Margin" Value="0,10,0,0"/>
<Setter Property="Width" Value="20"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<!--<Setter Property="IsEnabled" Value="False"/>-->
<!--<Setter Property="IsChecked" Value="False"/>-->
<Style.Triggers>
<DataTrigger Binding="{Binding ConcentratorViewModel.Manufacturer}" Value="ZIV">
<Setter Property="Background" Value="Red"/>
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding ConcentratorViewModel.Manufacturer}" Value="Landis+Gyr">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
The CheckBox must be Checked or Unchecked depending on the selected manufacturer. I added a converter to see the value on the trigger and it's correct. I've also added the Background property and it changes correctly, but the IsChecked doesn't work.
Well you need to move the IsChecked Binding inside the Style. Setting it directly on the Checkbox gives it precedence and the Trigger's cannot change that value.
So something like:
<CheckBox>
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Margin"
Value="0,10,0,0" />
<Setter Property="Width"
Value="20" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="IsChecked"
Value="{Binding ConcentratorViewModel.Integrated}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ConcentratorViewModel.Manufacturer}"
Value="ZIV">
<Setter Property="Background"
Value="Red" />
<Setter Property="IsChecked"
Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding ConcentratorViewModel.Manufacturer}"
Value="Landis+Gyr">
<Setter Property="IsChecked"
Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
Note:
Remember by doing this, your Binding only applies when the DataTrigger's do not evaluate to "True". Thus if your Manufacturer property is "ZIV" or "Landis+Gyr" then your Integrated property is not going to see any CheckBox updates even with a TwoWay binding as it just isn't being used.
I have a listview that contains log messages. I want to set the background color for each row in listview according to the severity of its corresponding entry. I do this using DataTrigger (see the example).
I would also like to support AlternationIndex for listview.
How can I combine them in xaml DataTrigger abd Trigger for background color of row?
For set background color for row I use the following code:
<ListView ... >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Severity} Value="Info">
<Setter
Property="Background"
Value="{Binding Path=Severity,
Converter=
{StaticResource msgSeverityToColorConverter}}"
/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Severity} Value="Error">
<Setter
Property="Background"
Value="{Binding Path=Severity,
Converter=
{StaticResource msgSeverityToColorConverter}}"
/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
And for AlternateIndex I have the following code:
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightBlue"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightGray"></Setter>
</Trigger>
</Style.Triggers>
I need that when row with message is not Info or Error, it will be of color from AlternationIndex property.
It's all due to order of declarations of triggers. First declare the alternation triggers and then the severity triggers.
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightBlue"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightGray"></Setter>
</Trigger>
<DataTrigger Binding="{Binding Path=Severity} Value="Info">
<Setter Property="Background"
Value="{Binding Path=Severity,
Converter="{StaticResource msgSeverityToColorConverter}}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Severity} Value="Error">
<Setter Property="Background"
Value="{Binding Path=Severity,
Converter="{StaticResource msgSeverityToColorConverter}}" />
</DataTrigger>
</Style.Triggers>
I have the following Data template with triggers:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsCalled}" Value="Yes">
<Setter TargetName="labelNumber" Property="Background" Value="Green" />
<Setter TargetName="labelNumber" Property="BorderThickness" Value="5" />
<Setter TargetName="labelNumber" Property="BorderBrush" Value="Blue" />
</DataTrigger>
<DataTrigger Binding="{Binding IsCalled}" Value="JustCalled" >
<Setter TargetName="labelNumber" Property="Background" Value="Pink" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Rather than individually set the label properties I want to call a style like the below:
How would get the Data Template to use the style above.
thank you
You can use a setter like
<Setter TargetName="labelNumber" Property="Style" Value="{StaticResource myLabelStyle1}" />
but you'll need to make sure you're not setting any properties locally on the labelNumber Label because they'll override any Style settings. You'll need another Style for your Label to set any properties for its default state in addition to the ones in the Triggers.
<Label Style="{StaticResource myDefaultLabelStateStyle}"/>
hey i wanna change row foreground color according to a boolean in the model, whats the best way of doing it?
Define the style as following (IsBlah is a boolian property):
<Style x:Key="MyRowStyle" TargetType="{x:Type dg:DataGridRow}">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="DarkBlue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBlah}" Value="False" >
<Setter Property="Background" Value="DarkGray" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
Your DataGrid should have a custom RowStyle. (RowStyle="{StaticResource MyRowStyle})
This is basically the same answer as Boris, but here's the syntax if you prefer to define the style directly within the DataGrid definition.
Note: Blend won't give you a live preview of this so you'll have to run it
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding HasErrors}" Value="True">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>