Refactor multiple triggers into one - wpf

Is it possible to reduce this to a single trigger?
<Style x:Key="StatusTextBlock" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text,
RelativeSource={RelativeSource Self}}" Value="Running">
<Setter Property="Foreground" Value="Green"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Text,
RelativeSource={RelativeSource Self}}" Value="Paused">
<Setter Property="Foreground" Value="Yellow"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Text,
RelativeSource={RelativeSource Self}}" Value="Stopped">
<Setter Property="Foreground" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>

If "Running" and "Stopped" are the only two available cases, you can set one as a property, and only use one trigger:
<Style x:Key="StatusTextBlock" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" /> <!--default case == Running -->
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text,
RelativeSource={RelativeSource Self}}" Value="Stopped">
<Setter Property="Foreground" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>

Related

How to change the text color for an unchecked row in xaml

I would like to gray out the text associated to an unchecked row in my application using xaml. I tried the following, but it is getting overwritten:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="cbkSelect"
IsChecked="{Binding Path=IsSelectedForOrder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
As the Foreground color should be applied to all cells of a given row, you can remove the trigger. The trigger inside the CellTemplate will only apply to to the CheckBox that the style is applied to.
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="cbkSelect"
IsChecked="{Binding Path=IsSelectedForOrder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
If you want to apply the foreground color in normal state, but not in selected state, add this RowStyle.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelectedForOrder}" Value="True">
<Setter Property="Foreground" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
If you want to apply the style in selected state, too, add this CellStyle. In this case a RelativeSource binding is used to access the data context of the row which contains IsSelectedForOrder.
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Style.Triggers>
<DataTrigger Binding="{Binding DataContext.IsSelectedForOrder, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True">
<Setter Property="Foreground" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>

WPF DataGrid: How do you set the style of the first row only?

I've tried searching for the answer, but the question that's been posted here has not been answered.
I've tried some complicated XAML, but it's never worked. The code below grays out all rows if the first row is selected. I need to gray out the first row only, regardless of which row index is selected.
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontStyle" Value="Normal"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=SelectedIndex, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="FontStyle" Value="Italic"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
Would anyone be able to help?
Thanks.
You can use the AlternationCount property found on all ItemsControls (ref ListBox).
<DataGrid ItemsSource="{Binding Items}"
AlternationCount="2147483647"
...
>
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="FontStyle" Value="Italic"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
...
</DataGrid>
EDIT
<DataGrid ItemsSource="{Binding Items}"
AlternationCount="2"
VirtualizingStackPanel.IsVirtualizing="False">
...
>
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Gray"/>
</Trigger>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource Mode=PreviousData}}"
Value="{x:Null}">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="FontStyle" Value="Italic"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
...
</DataGrid>

CheckBox text to change based on its IsChecked

I want a CheckBox text to changed based on the IsChecked status.
Tried with the following, but it complains about not having the property Content
<CheckBox Name="IsManualInput" IsChecked="{Binding Path=IsManual, Mode=TwoWay}" >
<CheckBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Value="True" >
<Setter Property="Content" Value="Manual" />
<Setter Property="IsReadOnly" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Value="True" >
<Setter Property="Content" Value="Define manually..." />
<Setter Property="IsReadOnly" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
It's a simple mistake, you need to include TargetType in your Style.
e.g.
<Style TargetType="{x:Type CheckBox}">

DataTrigger setter doesn't fire up

I have a two radioButtons and two textboxs
<RadioButton x:Name="AdmLnkRadio1" GroupName="AdmLnkgr1" Content="Link #1"/>
<RadioButton x:Name="AdmLnkRadio2" GroupName="AdmLnkgr1" Content="Link #2"/>
<TextBox x:Name="AdmLnkTextBoxName1" />
<TextBox x:Name="AdmLnkTextBoxName2" IsEnabled="False" >
<TextBox.Style>
<Style BasedOn="{StaticResource TextBoxBase}" TargetType="TextBox" >
<Style.Triggers>
<!--Trigger 1 -->
<DataTrigger Binding="{Binding ElementName=AdmLnkRadio1, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=AdmLnkTextBoxName1, Path=Text}"></Setter>
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
<!--Trigger 2 - Doesn't Fires UP!!!! -->
<DataTrigger Binding="{Binding ElementName=AdmLnkRadio2, Path=IsChecked}" Value="True">
<Setter Property="Text" Value=""></Setter>
<Setter Property="IsEnabled" Value="True"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
When user checks radiobutton 1 the trigger 1 works and second textbox text binds to the text of the first one. But when the second radiobutton is checked, the second trigger should fire up, but it doesn't. Thanks for any help
It does fire but because you're setting IsEnabled to fixed False value your style does not override it (Dependency Property Setting Precedence List). Try setting IsEnabled in your Style, like this
<TextBox x:Name="AdmLnkTextBoxName1" />
<TextBox x:Name="AdmLnkTextBoxName2">
<TextBox.Style>
<Style TargetType="TextBox" >
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=AdmLnkRadio1, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=AdmLnkTextBoxName1, Path=Text}"/>
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=AdmLnkRadio2, Path=IsChecked}" Value="True">
<Setter Property="Text" Value=""/>
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>

Unable to change background for a Wpf toolkit autocompletebox?

How should i change the background of the wpftoolkit autocompletebox.? I tried by subscribing to enabledchanged event and changed the background of the control which is not changing at all.Can any body help.
<WpfToolkit:AutoCompleteBox x:Name="txtBxSearch" Background="White" IsTextCompletionEnabled="True" MinimumPrefixLength="0" FilterMode="Contains" Height="24" Width="150" KeyDown="txtBxSearch_KeyDown" >
<WpfToolkit:AutoCompleteBox.TextBoxStyle>
<Style TargetType="TextBox">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</Style>
</WpfToolkit:AutoCompleteBox.TextBoxStyle>
</WpfToolkit:AutoCompleteBox>
You can do this in XAML:
<toolkit:AutoCompleteBox
ToolTip="Enter the path of an assembly."
x:Name="tbAssembly" Height="27" Width="200"
Populating="tbAssembly_Populating"
>
<toolkit:AutoCompleteBox.Style>
<Style TargetType="toolkit:AutoCompleteBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=tbAssembly, Path=IsEnabled}" Value="True">
<Setter Property="Background" Value="Yellow" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=tbAssembly, Path=IsEnabled}" Value="False">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</toolkit:AutoCompleteBox.Style>
</toolkit:AutoCompleteBox>

Resources