Why is this DataTrigger not working after a PropertyChanged? - wpf

The following triggers work almost as expected:
<Style.Triggers>
<Trigger Value="True" Property="IsSelected">
<Setter Property="Foreground" Value="White" />
</Trigger>
<DataTrigger Value="True" Binding="{Binding UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InUseConverter}}">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
</Style.Triggers>
After loading the view, the colors are correct.
Then I execute an async taks en when it has finished I give the propertychanged on the object that has the binding to my datagrid-row.
But why is the DataTrigger not fired (I have to refresh the view to see the effect)?
EDIT:
My problem is that I don't now which property I have to give the PropertyChanged.
Some details about the datagrid (Projects is an ObservableCollection):
DataGrid SelectedItem="{Binding Project}" ItemsSource="{Binding Projects}">
The property of object Project that the binding must use is:
Project.Variants[0].InUse
I tried also the triggers:
<DataTrigger Value="True" Binding="{Binding Path=Variants[0].InUse, Converter={StaticResource NotNullConverter}}">
<DataTrigger Value="True" Binding="{Binding Path=., Converter={StaticResource InUseConverter}}">
In the view model I have tried after Project.Variants[0].InUse = null;:
Project.OnPropertyChanged("InUse");
Project.Variants[0].OnPropertyChanged("InUse");
raisePropertyChanged("Project.Variants[0].InUse");
raisePropertyChanged("Variants[0].InUse");
raisePropertyChanged("Projects");
raisePropertyChanged("Project");
raisePropertyChanged("InUse");

At last it works using:
<DataTrigger Value="True" Binding="{Binding Path=Variants[0].InUse, Converter={StaticResource NotNullConverter}}">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
Project.Variants[0].OnPropertyChanged("InUse");

Try to set Foreground property in your style to change it dynamically at runtime
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Value="True" Property="IsSelected">
<Setter Property="Foreground" Value="White" />
</Trigger>
<DataTrigger Value="True" Binding="{Binding UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InUseConverter}}">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
</Style.Triggers>

Related

DataTrigger inside a MultiDataTrigger?

I want to change 2 Properties on 2 different conditions using Multi-/DataTrigger.
I have 1 Button which changes its IsEnabled Property when ValidationRule returns an error.
I also want to change the Command Property of this Button but on other conditions.
<Button Content="Save">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource MaterialDesignFlatButton}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=FirstNameBox}" Value="False" />
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=LastNameBox}" Value="False" />
[...]
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Now I want to implement another Trigger which changes the Binding of the Command Property when anoither Propertie's Binding equals to XY.
So i need to implement this next to the Datatrigger above.
<Setter Property="Command" Value="{Binding CreateEmployeeCommand}" />
<DataTrigger Binding="{Binding CurrentManageMode}" Value="2">
<Setter Property="Command" Value="{Binding EditEmployeeCommand}" />
</DataTrigger>
So is it even possible to have 2 Triggers at the same time?
Okay, i fixed it adding another Trigger just in Style.Triggers.
I didn't tried this cuz many Controls/Properties doesn't allow multiple Content.
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource MaterialDesignFlatButton}">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Command" Value="{Binding CreateEmployeeCommand}" />
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentManageMode}" Value="2">
<Setter Property="Command" Value="{Binding EditEmployeeCommand}" />
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=FirstNameBox}" Value="False" />
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=LastNameBox}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>

Eliminate duplicate DataTrigger logic

I have a status bar that, via data binding and triggers, shows whether a user is connected to a server. I'm styling two different elements to achieve this: the actual StatusBarItem to set a colored background (red, green, yellow), and a TextBlock inside to display the text ("Not Connected", "Connected" etc.) As I'm doing this in XAML, I have to duplicate the DataTrigger logic across two styles (to update the background in one and text in another), like so:
<StatusBarItem Grid.Column="0" HorizontalAlignment="Left" Padding="10,0,10,0">
<StatusBarItem.Style>
<Style TargetType="StatusBarItem">
<Setter Property="Background" Value="Red" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.NotConnected}">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.Connected}">
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.OfflineMode}">
<Setter Property="Background" Value="Goldenrod" />
</DataTrigger>
</Style.Triggers>
</Style>
</StatusBarItem.Style>
<TextBlock Width="Auto" Height="Auto">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="Not Connected" />
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.NotConnected}">
<Setter Property="Text" Value="Not Connected" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.Connected}">
<Setter Property="Text" Value="Connected to Perforce" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.OfflineMode}">
<Setter Property="Text" Value="Offline Mode" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StatusBarItem>
Question: is there a way to compress this code and not duplicate the DataTrigger logic?
Please note that I'm not interested in solutions that make the TextBlock fill out the entire StatusBarItem. Sure, that would solve this particular issue (I'd just style the TextBlock for both background color and text). But it doesn't address the issue at large (duplicate code that has to be updated in two places).
In this particular case you could set the Content property using the DataTriggers in the StatusBarItem style instead of using an explicit TextBlock as the Content:
<StatusBarItem Grid.Column="0" HorizontalAlignment="Left" Padding="10,0,10,0">
<StatusBarItem.Style>
<Style TargetType="StatusBarItem">
<Setter Property="Background" Value="Red" />
<Setter Property="Content" Value="Not Connected" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.NotConnected}">
<Setter Property="Background" Value="Red" />
<Setter Property="Content" Value="Not Connected" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.Connected}">
<Setter Property="Background" Value="Green" />
<Setter Property="Content" Value="Connected to Perforce" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ConnectionStatus}" Value="{x:Static local:EConnectionStatus.OfflineMode}">
<Setter Property="Background" Value="Goldenrod" />
<Setter Property="Content" Value="Offline mode" />
</DataTrigger>
</Style.Triggers>
</Style>
</StatusBarItem.Style>
</StatusBarItem>
Another option would be to define your own custom ControlTemplate for the StatusBarItem and use ControlTemplate.Triggers to change the background and the text in one place.

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}">

wpf vb.net Datagrid image in row depending on value in cell

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>

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>

Resources