DataTrigger binding to a get-only property - c#

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.

Related

Data trigger in static resource

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>

Binding with or condition

i have two check boxes and a text box. the text box's IsEnabled property should be binded to both of those check box's IsChecked Properties. if one of check box or both of them are enabled then text box should be enabled.
the first solution that came to my mind was multibinding. But it needs another class to do. Is there any easier way to do this?
You can do that with two DataTriggers on TextBox Style where you can enable TextBox in case any checkBox is checked.
<CheckBox x:Name="checkBox1"/>
<CheckBox x:Name="checkBox2"/>
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=checkBox1}"
Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=checkBox2}"
Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
I think not - I would really like "and" or "or" expressions in xmal, but they are not provided.
I stumpled upon this library, which claims to add them:
http://wpfconverters.codeplex.com/
But I never used them extensively.

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>

Change property depending on property in other control - WPF

I want to use some kind of trigger to change a button in my window to IsEnabled = False when the textbox property Validation.HasErrors of my textbox is True.
Can I do this with Triggers of some kind on the Button?
If yes, some example would be nice!
You can do this by using a Style. If you want to tie it directly to the text box, you could do something like this:
<Style x:Key="DisabledOnErrors" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding (Validation.HasErrors)}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBox x:Name="myTextBox" />
<Button Style="{StaticResource DisabledOnErrors}"
DataContext="{Binding ElementName=myTextBox}" />
This works if the button is not already binding to the DataContext for other properties. In this case, the Style is reusable for other button and text box pairings.
Yes, you can do this with triggers, but because you are referring to another element, you must use a DataTrigger rather than a normal Trigger:
<Button>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding (Validation.HasError), ElementName=tb}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Note you must use a Style rather than the Button.Triggers collection, because Button.Triggers can contain only EventTriggers.

Categories