DataTrigger setter will not update property. Why? - c#

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

Related

MultiDataTrigger with multiple ComboBoxes WPF

I would like to enable button only when all specified ComboBoxes have values. However, as soon as I add a second condition, button is enabled from the start
Here is my code
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=SensorPartNumberComboBox, Path=SelectedValue}" Value="{x:Null}"/>
<Condition Binding="{Binding ElementName=SensorTypeComboBox, Path=SelectedValue}" Value="{x:Null}"/>
<Condition Binding="{Binding ElementName=SensorBrandNameComboBox, Path=SelectedValue}" Value="{x:Null}"/>
<Condition Binding="{Binding ElementName=DimmingProtocolComboBox, Path=SelectedValue}" Value="{x:Null}"/>
<Condition Binding="{Binding ElementName=Wired_WirelessComboBox, Path=SelectedValue}" Value="{x:Null}"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
I would appreciate any help!
MultiDataTrigger requires all of the conditions to be true for it to take effect. I.e. it's equivalent to a logical AND.
In your example, if any value is non-null, the trigger won't take effect and the button will remain enabled.
For a logical OR, instead of using MultiDataTrigger, just use multiple DataTrigger. If any condition of any trigger is true, then that trigger will take effect, with precedence over the default setter for the property in the style.
For example:
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SensorPartNumberComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
<DataTrigger/>
<DataTrigger Binding="{Binding ElementName=SensorTypeComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
<DataTrigger/>
<DataTrigger Binding="{Binding ElementName=SensorBrandNameComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
<DataTrigger/>
<DataTrigger Binding="{Binding ElementName=DimmingProtocolComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
<DataTrigger/>
<DataTrigger Binding="{Binding ElementName=Wired_WirelessComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
<DataTrigger/>
</Style.Triggers>
Alternatively, you might consider putting the logic in your view model, with a single bool property you bind to, and which is set according to the bound SelectedValue properties for the various ComboBox controls.
Yet another alternative would be to use MultiBinding to bind the five view model properties that are bound to the ComboBox.SelectedValue properties, with a IMultiValueConverter that implements the logic.
Of course, these last two options work only if you've got a proper view model with binding set up in the first place (something I strongly encourage, if you haven't already).

Enabling TextBox with trigger

I want a Textbox to be disabled, except the user hovers with the mouse over it. But this does not seam to work, the Textbox is still not editable if I hover over it. (Yes I know that this is unusual.)
What I tried is:
<Border>
<TextBox Text="Hover to edit me!" IsEnabled="False" >
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Border}, Path=IsMouseOver}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<!-- this does not work either -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<!-- neither did this -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsEnabled" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Border>
I wonder if it is possible at all using a trigger?
This is because of the Dependency Property Value Precedence in WPF.
You need to set the IsEnabled property to false in the Style, so the trigger can override the value.
The local value has always a higher priority, so setting IsEnabled="False" directly in the text box will override any style or style trigger value.
Here is a working example:
<Border>
<TextBox Text="Text">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsMouseOver,
RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Border>

Finding the Content of a ContentPresenter and setting styles

I couldn't find an appropriate topic for my problem. I have the following code.
<ContentPresenter x:Name="ContentPresenter"
VerticalAlignment="Center"
Width="Auto"/>
<TextBox x:Name="TextBlockFront" >
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=TextBlockFront, Path=IsFocused}" Value="true"/>
<Condition Binding="{Binding ElementName=ContentPresenter, Path=ContentProperty}" Value="ComboBox"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Hidden"/>
<Setter Property="Text" Value="{Binding ElementName=ContentPresenter,Path=SelectedItem}"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
I want to get the clarification about the second condition of my MultiTrigger. I am relative new to WPF and I would appreciate any help in sorting out my doubt.
Expected behaviour:
when the TextBox is focused AND the ContentPresenter is ComboBox then I want to set the above properties. If the ContentPresenter is TextBox then I will set the Text property instead of SelectedItem

WPF treeview item visibility binding to property + static variable

I have a WPF treeview, with nodes visibility dependent on their "Deleted" binding property:
<Style x:Name="SelectedTreeItem" TargetType="TreeViewItem">
<EventSetter Event="MouseRightButtonDown" Handler="TreeSetup_MouseRightButtonDown"/>
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding Deleted}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
I would like to make add some way to ignore this deleted property value. This would be achieved by a button "Show deleted items".
I do not want to change the "Deleted" value, but rather add a global condition to that forces this binding to ignore untill the button is pressed again.
You can do that via MultiDataTrigger.Conditions. Here is an example for visibility:
<Style>
<Setter Property="Control.Visibility" Value="Visible" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsPropA}" Value="false" />
<Condition Binding="{Binding Path=IsPropB}" Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Hidden" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
I used the other answer in conjuction with a static resource
<Style>
<Setter Property="Control.Visibility" Value="Visible" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsPropA}" Value="false" />
<Condition Binding="{Binding Source={StaticResource ClassName},Path=PropertyName}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Hidden" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
Just had to create the local resource under Window resources:
<Window.Resources>
<local:ClassName x:Key="ClassName"/>
And then the button used to show deleted or not:
private void btnApply_Click(object sender, RoutedEventArgs e)
{
//ApplyGeneralChanges();
var item = this.FindResource("ClassName") as ClassName;
item.DisplayDeleted = !item.DisplayDeleted;
}

MultiDataTrigger with Custom DependencyProperty

I have a MultiDataTrigger. I can bind to a DependencyProperty (DP) of the control and a view model property like this
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True"/>
<Condition Binding="{Binding PerformTextSearchesInCommentary}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="LightGray"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
Great. But now, I want to use my own custom DP "HasTextMatch", which is defined in a static class. I can do this with a standard trigger like
<Style.Triggers>
<Trigger Property="Helpers:DataGridTextSearch.HasTextMatch" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
But I now want to include another Property. I have tried
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<!--<Condition Property="Helpers:DataGridTextSearch.HasTextMatch" Value="True"/>--> This obviously won't work.
<Condition Binding="{Binding Helpers:DataGridTextSearch.HasTextMatch, RelativeSource={RelativeSource Self}}" Value="True"/>
<Condition Binding="{Binding PerformTextSearchesInCommentary}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="LightGray"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
But this does not work. I have searched but cannot seem to find out how to do this. How can I get the binding to my custom DP?
Thanks for your time.
The DataGridTextSearch.HasTextMatch property is an attached property. Please use the following Condition:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Helpers:DataGridTextSearch.HasTextMatch), RelativeSource={RelativeSource Self}}>
...
Additional information about property path (including attached properties) can be found here: PropertyPath XAML Syntax, MSDN.

Categories