Data trigger in static resource - c#

I would like to make a template style, which I can use as a static resource, like this:
<TextBox
Style="{StaticResource CollapsingTextBox}"
Text="{Binding SomeNullableValue}" />
Now as the name suggests, I would like the text box to collapse, when the binding value is null. Normally I would do this with a data trigger, like this:
<DataTrigger Binding="{Binding SomeNullableValue}" Value="{x:null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
But if I move the data trigger to a template style, which can be reused, then I it's no good to bind directly to the binding property (i.e. SomeNullableValue). Instead I need to bind the the binding of the template user (if that makes sense).
How do I achieve this kind of binding?

try a Trigger with Text property:
<Trigger Property="Text" Value="">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="Text" Value="{x:null}">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>

Related

XAML "The member `isChecked` is not recognized or accessable" error for a RadioButton style trigger

I have two RadioButtons that I'd like to change the text on based on their IsChecked state, but Visual Studio is telling me IsChecked and Content aren't recognized/accessable. The below code is the same for both buttons.
<RadioButton GroupName="{Binding CommunicatingGroupName}" IsChecked="{Binding IsCommunicating}" IsEnabled="{Binding IsActive}" FontSize="11" TextOptions.TextFormattingMode="Display" Content="ACTIVE" >
<RadioButton.Style>
<Style TargetType="{StaticResource ButtonBlue}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Content" Value="ACTIVE" />
</Trigger>
<Trigger Property="IsChecked" Value="false">
<Setter Property="Content" Value="STANDBY" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Content" Value="ACTIVE" />
</Trigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
I have ToggleButtons elsewhere in the file that work with the same <Style.Triggers> elements, and as far as I know should work the same way for these RadioButtons. Am I missing something specific to RadioButtons? I've rebuilt, restarted VS, etc. and the errors persist.
Look at this line:
<Style TargetType="{StaticResource ButtonBlue}">
You set target type to something that looks like style. Probably you tried to write something like this:
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource ButtonBlue}">

DataTrigger setter will not update property. Why?

XAML :
<RadioButton x:Name="RadioButtonA">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
C# Code behind
public bool RadioAValue
{
get
{
...
}
set
{
...
}
}
set section of RadioAvalue will not be called when CheckBoxA is checked.
Any reason why?
Problem in your code
You are setting the binding in Style Setter
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
and on clicking the checkbox you have overwriting the Binding with the value False. Now there is no more Bindings over the element and it wont call the set anymore.
Also, if you try to bind it over the RadioButton itself instead of setters that will take more precedence and your Triggers won't work there.
Solution
I would recommend you to have Command binding over the Checkbox and update the value RadioAValue from your ViewModel
If you want conditional setter use MultiBinding, right now you block binding with already setted value
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
Must be something like this (didn't test thought):
<RadioButton x:Name="YouRadioButton">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding RadioAValue}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="IsChecked" Value="True"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<DataTrigger Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="False">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<CheckBox x:Name="CheckBoxA"/>

DataTrigger binding to a get-only property

Is it possible to bind a property with no setter to a DataTrigger in WPF? I have the following code and the property's getter is not called as expected:
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsLoggedIn}" Value="True">
<Setter Property="Text" Value="Connected" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding IsLoggedIn}" Value="False">
<Setter Property="Text" Value="Disconnected" />
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
public bool IsLoggedIn
{
get { return Connection.IsLoggedIn; }
}
INPC is implemented properly (though I don't think that actually matters in this situation) and properties with setters behave properly. Is it possible to bind this property to a DataTrigger (and have it update properly) as it stands now?
Its possible. Why not?
Its all fine with having just a getter on the source side of binding. Target of the binding must be a dependency property but the source can be anything.
If you wish changes to be fired properly you will have to fire PropertyChanged with property name IsLoggedIn too once Connection.IsLoggedIn gets changed.

One setting is determined by the second settings

I have the same options in different WPF dialog. One option that depends on another. If I click on the first, I also want to check the second. Both options correspond to the private bool variable in different classes. What is the best solution for this problem?
You could do that in WPF/XAML with Style.Triggers. For example the following code is an example on how to bind a textblock control's IsEnabled status based on the status of a checkbox (checked/unchecked)
<TextBlock Text="mytextblockText: ">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,ElementName=myCheckbox}" Value="False">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=myCheckbox}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
For a checkbox being checked when another checkbox is checked, it looks like this (I guess)
<CheckBox>
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,ElementName=myCheckbox}" Value="False">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=myCheckbox}" Value="True">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
*edit
can the properties in the classes be changed by something different than by those checkboxes? If yes, you could fire an event when the property is changed or directly manipulate the checkstate of the according box. Also, are the boxes dependent on each other? Or is just one dependent on the other (A <=> B or A => B)?
For manipulating the properties when one of the boxe's state is changed you could use the Checked/Unchecked events. Or use DependencyProperty as described in Pat's answere over here

Using Bindings to trigger a style change

Hopefully someone can help here.
I have a ListView that is populated by a List Property in my ViewModel.
I have another List Property in my ViewModel that contains the Rows in the UI I need highlighting.
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
This does exactly what is looks like, any item I select in the ListView highlights in Red.
I want to be able to Bind this style trigger to the List property in my ViewModel.
Anybody know how this can be achieved?
Create a property called IsSelected on your item and bind it to your ListViewItem.IsSelected
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
Edit
If you want to apply other style setters based on a property in your DataItem, use a DataTrigger instead of a regular Trigger. Regular Triggers are only meant to be used on UI Element properties, not bindings.
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding IsHighlighted}" Value="True">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>

Categories