I need to set the tabstop of a textbox based on whether or not the bound property has data or not. The properties are nearly all strings - I want to disable the tabstop if the property is null or empty.
I am using a style for these textboxes.
Here is the style I am currently using:
<Style TargetType="TextBox" x:Key="FauxLabel">
<Setter Property="Background" Value="Transparent" />
<Setter Property="IsTabStop" Value="True" />
<Setter Property="IsReadOnly" Value="True" />
<!-- rest of setters truncated -->
</Style>
And here is an example of my usage:
<TextBox
Name="Account"
Style="{StaticResource ResourceKey=FauxLabel}"
Text="{Binding
Path=SelectedItem.AccountNumber,
ElementName=CrfResults}"/>
In this exmple, if the AccountNumber property is null or empty, I want to disable the tabstop. I am using Visual Studio 2010 and .Net 4.0. Can anyone help me out?
Update:
Thanks to Rachel for her answer. I was able to update the style to handle all textboxes using that style using by adding the trigger below which binds to the text property, rather than the underlying bound property:
<Style.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="IsTabStop" Value="False">
</Setter>
</Trigger>
<Trigger Property="Text" Value="">
<Setter Property="IsTabStop" Value="False">
</Setter>
</Trigger>
</Style.Triggers>
Use a DataTrigger which checks if the value is {x:Null}
<Style TargetType="TextBox" x:Key="FauxLabel">
<Setter Property="IsTabStop" Value="True" />
<Style.Triggers>
<DataTrigger Property="{Binding ElementName=CrfResults, Path=SelectedItem.AccountNumber}" Value="{x:Null}">
<Setter Property="IsTabStop" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
You could probably do it with a regular Trigger instead of a DataTrigger too
Related
I'm trying to fire a trigger when a property in my ViewModel changes. I can't seem to get the trigger to fire no matter what I try. My XAML looks like this:
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Padding" Value="0 1" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsExpanding}" Value="True">
<Setter Property="Control.Template" Value="{StaticResource ResourceKey=loadingTreeViewItem}" />
</DataTrigger >
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
The IsExpanded and IsSelected bindings are working fine, however I can't get the DataTrigger to fire when IsExpanding is true. These properties are in the same ViewModel. I have tried adding different variations for RelativeSource but am not having any luck. Any feedback is appreciated.
Turns out the trigger was working. The problem was that the IsExpanding property and the call to get the data for the TreeView were both happening on the UI thread. I threaded the call to get the data and everything is working as expected
I want to set the border for a DataGrid Row which is currently having the focus. But not the seleced row because when the Multi selection is enabled for the datagrid then there is a chance that multiple rows can be selected.
I need a solution in XAML
Thanks in advance!
Add this to DataGridRow's style (either using Resources, or by setting DataGrid.RowStyle):
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
Try IsKeyboardFocusWithin Property
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin"
Value="True">
<Setter Property="BorderBrush"
Value="Red" />
</Trigger>
</Style.Triggers>
I have many TextBox controls and I'm trying to write a style that clears the Text property when the Control is disabled.
I don't want to have Event Handlers in code behind.
I wrote this:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
The problem is that if the TextBox is defined like:
<TextBox Text={Binding Whatever} />
then the trigger does not work (probably because it's bound)
How to overcome this problem?
Because you're explicitly setting the Text in the TextBox, the style's trigger can't overwrite it. Try this:
<TextBox>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Text" Value="{Binding Whatever}" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
In WPF is there some mechanisim to reuse the property setters amoung differant triggers? For example I have the following.
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter Property="Content" Value="Not Connected" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding IsConnected}" Value="False">
<Setter Property="Content" Value="Not Connected" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Content" Value="Connected" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
The setters for Null and False are identical and it would be nice if there was only a single point of change.
You can always create a resource like this:
<Setter x:Key="setter1" Property="Content" Value="Not Connected" />
However, you cannot use resource keys as object in a collection.
You could set somewhere
<SomeObject Setter="{StaticResource setter1}"/>
but Setters are almost always added to collections and you cannot add resource keys in xaml collection syntax.
The only scenario I can think of which would support this would be to create a SetterBaseCollection resource with those two identical pairs of Setters,
<SetterBaseCollection x:Key="settersKey">
<Setter Property="Label.Content" Value="Not Connected" />
<Setter Property="Label.Foreground" Value="Red" />
</SetterBaseCollection>
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}" Setters="{StaticResource settersKey}"/>
// ...
</Style.Triggers>
</Style>
but the DataTrigger.Setters collection property is readonly and cannot be set from xaml.
So, the answer would be no.
In this special case, it would be best to make the unconnected case the default (without a condition), and only create a DataTrigger for the one case that is different.
hey i wanna change row foreground color according to a boolean in the model, whats the best way of doing it?
Define the style as following (IsBlah is a boolian property):
<Style x:Key="MyRowStyle" TargetType="{x:Type dg:DataGridRow}">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="DarkBlue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBlah}" Value="False" >
<Setter Property="Background" Value="DarkGray" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
Your DataGrid should have a custom RowStyle. (RowStyle="{StaticResource MyRowStyle})
This is basically the same answer as Boris, but here's the syntax if you prefer to define the style directly within the DataGrid definition.
Note: Blend won't give you a live preview of this so you'll have to run it
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding HasErrors}" Value="True">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>