How to bind a DataTrigger to a non-bound attribute? - wpf

This is not in a template, it is a <Label> in the body of my XAML document. Notice that the Content of the label is set to 'PENDING'. This is monitoring a server connection and at various times the code-behind might change the value of the content to CONNECTED or ERROR. When that happens, I would like for the color of the text to change. I thought this would do it, but it doesn't... all I get is black text.
<Label x:Name="lbl_Connected" Content="PENDING" FontWeight="Bold" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource self}, Path=Content.Value}" Value="CONNECTED">
<Setter Property="Label.Foreground" Value="Green"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource self}, Path=Content.Value}" Value="PENDING">
<Setter Property="Label.Foreground" Value="Yellow"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource self}, Path=Content.Value}" Value="ERROR">
<Setter Property="Label.Foreground" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
Can someone tell me how I should be doing this?

Just remove the ".Value" part from the Binding's Path, i.e.:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource self}, Path=Content}" Value="CONNECTED">
<Setter Property="Label.Foreground" Value="Green"></Setter>
</DataTrigger>
Anyway if I were you, I would use a Binding in order to set the Label content and a converter to handle the Foreground color.

Related

Using multiple data triggers does not work

I want to detect when the selected item changes in a ListBox and a TreeView via DataTriggers
so this is my code
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=DirTreeView, Path=SelectedItemChanged}" Value="{x:Null}">
<Setter Property="Text" Value="{Binding ElementName=DirTreeView, Path=SelectedItem, Converter={StaticResource contentConverter}}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=listbox, Path=SelectionChanged}" Value="{x:Null}">
<Setter Property="Text" Value="{Binding ElementName=listbox, Path=SelectedItem, Converter={StaticResource contentConverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
if i comment out the last DataTrigger it works fine, but when I use both nothing works.
Why is that and how do I get this to work using both triggers?

Replace a text-converter dynamically

I have a textblock of a user-control which uses a converter to display figures. This converter gets loaded in a ResourceDictionary at the start of the application.
Now I'd like to exchange this converter with another one, to display a different format, depending on a parameter in the app-settings. Unfortunatley using just a trigger doesn't work. Is it possible to load a converter dynamically into the user-control, and put a reference on it from a textblock?
Edit: Here's my trigger attempt:
<TextBlock>
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mycontrol}, AncestorLevel=1}, Path=mode}" Value="0">
<Setter Property="TextBlock.Text" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type cg:Fader}, AncestorLevel=1}, Path=Figure, Converter={StaticResource ConverterA}}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mycontrol}, AncestorLevel=1}, Path=mode}" Value="1">
<Setter Property="TextBlock.Text" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type cg:Fader}, AncestorLevel=1}, Path=Figure, Converter={StaticResource ConverterB}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
The reason why triggers are not working in your example is in bindings. Overall Style + DataTriggers are perfectly suitable for dynamic template selection.

Set or change Converter using a trigger?

Here is my TextBox with a converter:
<TextBox Text="{Binding TimbraturaSelezionata.OrarioMinuti, Converter={StaticResource Minuti2HHmmConverter}}" Margin="5,0"/>
I searched for a way to set or change the converter only when it is effectively needed.
In fact I would like to put that TextBox inside a general purpose User Control and apply the converter only when a specific condition is met.
The only solution that came to my mind is to use a ContentControl and use two DataTrigger to set its template, one with the Converter inside the TextBox, and one without. I would hope finding a clearer way to achieve my goal.
Thanks for any suggestions.
Since you're set on a trigger. Here's an example. Hope it helps;
<TextBox x:Name="MyTextBox" Text="{Binding TimbraturaSelezionata.OrarioMinuti}" Margin="5,0">
<i:Interaction.Triggers>
<ei:DataTrigger Value="False"
Binding="{Binding YourCondition, ElementName=MyTextBox}">
<ei:ChangePropertyAction PropertyName="Text"
Value="{Binding TimbraturaSelezionata.OrarioMinuti}" />
</ei:DataTrigger>
<ei:DataTrigger Value="True"
Binding="{Binding YourCondition, ElementName=MyTextBox}">
<ei:ChangePropertyAction PropertyName="Text"
Value="{Binding TimbraturaSelezionata.OrarioMinuti, Converter={StaticResource Minuti2HHmmConverter}}" />
</ei:DataTrigger>
</i:Interaction.Triggers>
</TextBox>
Another working solution is the folowing:
<TextBox Width="100">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding ValoreInMinuti}" Value="True">
<Setter Property="Background" Value="Red" />
<Setter Property="Text" Value="{Binding Quantita, Converter={StaticResource Minuti2HHmmConverter}}" />
</DataTrigger>
<DataTrigger Binding="{Binding ValoreInMinuti}" Value="False">
<Setter Property="Background" Value="Yellow" />
<Setter Property="Text" Value="{Binding Quantita}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Note that the Text property is set only via DataTrigger. In my specific case I had only two possibilities, one with the converter and one without it.

WPF Styling and Templating over many buttons?

I can't seem to get the correct combination to get the desired effect:
Current XAML:
<Button Content="Foo" prism:Click.Command="{Binding FooCommand}"
Visibility="{Binding IsEnabled, RelativeSource={RelativeSource Self}, Converter={ncon:VisibilityBooleanConverter}}" />
<Button Content="Bar" prism:Click.Command="{Binding BarCommand}"
Visibility="{Binding IsEnabled, RelativeSource={RelativeSource Self}, Converter={ncon:VisibilityBooleanConverter}}" />
I want to extract out the Visibility="{Binding IsEnabled, RelativeSource={RelativeSource Self}, Converter={ncon:VisibilityBooleanConverter}}" as a style to apply over all the Buttons (within this UserControl resources). I can't seem to get the correct combination going here to make that happen.
Basically, what it does is instead of just disabling the button based on the ICommand.CanExecute it takes that DependencyProperty and binds it to the Visibility of the Button using a boolean-visiblity converter so the button is not only disabled, but also collapsed.
Style would look like this i suppose:
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility"
Value="{Binding IsEnabled, RelativeSource={RelativeSource Self}, Converter={ncon:VisibilityBooleanConverter}}"/>
</Style>
Doesn't that work?
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}, Converter={ncon:VisibilityBooleanConverter}}" Value="Visible">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>

wpf: override label content when currently bound item is null

I want to set a Label (or TextBox) default string as long as the binding value is null. This works fine for any other property than Content, for example:
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/Label}">
<Label.ContentStringFormat>Details for pump curve: {0}</Label.ContentStringFormat>
<Label.Style>
<Style TargetType="Label" BasedOn="{StaticResource header}">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/}" Value="{x:Null}">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
The above will change the background of the label to red as long as there is no CurrentItem in the pumpCurvesViewSource, but what I really want to do is change the background trigger to this:
<Setter Property="Content" Value="No pump curve selected"></Setter>
But this does not work (I'm guessing it is because the Content is already bound and my setting would override the binding).
Does anyone know how to accomplish this?
have you tried TargetNullValue?
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/Label, TargetNullValue='No pump curve selected'}">
If found a way of accomplishing the same thing, but with a bit more code than I liked:
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/Label}">
<Label.ContentStringFormat>Details for pump curve: {0}</Label.ContentStringFormat>
<Label.Style>
<Style TargetType="Label" BasedOn="{StaticResource header}">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/, Mode=OneWay, Converter={StaticResource isNullConverter}}" Value="True">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label Content="No pump curve selected">
<Label.Style>
<Style TargetType="Label" BasedOn="{StaticResource header}">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/, Mode=OneWay, Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
the shortest answer would be:
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource, FallbackValue=Your Default String}, Path=/Label}">

Resources