Xaml trigger on a TextBox, bound to a MVVM property not triggering - c#

I am a noob at Xaml triggers.
Do you see any obvious reason why this trigger does not work:
<TextBox Text="{Binding TiretNom}" Margin="1">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding TiretNom}" Value="">
<Setter Property="TextBox.Background" Value="Tomato"/>
</DataTrigger>
<DataTrigger Binding="{Binding TiretNom}" Value="a">
<Setter Property="TextBox.BorderBrush" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Neither does the backround change when the property TiretNom = "",
nor does the borderbrush gets red if TiretNom = "a"
Thx in advance.

Related

WPF XAML - Design time and visibility of textbox

I use Visual Studio 2019 with WPF / MVVM.
I have set a trigger to a textbox to control its visibiliy.
And during runtime this works well, the trigger checks the state of a radiobutton and sets the visibiliy of the textbox accoring to the radiobutton's state.
But during designtime this textbox is not visible.
How could I make this textbox to be visible during designtime ?
This is the XAML I have for the trigger:
<Style x:Key="text" TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Radiobutton1, Path=IsChecked}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Radiobutton1, Path=IsChecked}" Value="false">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBox Style="{StaticResource text}" Text="test..... />
I found this article https://social.msdn.microsoft.com/Forums/en-US/cacc5c30-8aa0-43c5-ad07-b063028653a2/designmode-and-visibility?forum=wpf and did some tests using "DesignerProperties.IsInDesignMode" but I can not make this run,I get errors like "datatrigger can not be added to setterbasecollection".
Also I don't know if "DesignerProperties.IsInDesignMode" is the right approach...
I think the answer is even simpler. By adding d:Visibility="Visible", the textbox will be visible at design time.
<TextBox d:Visibility="Visible" Style="{StaticResource text}" Text="test..... />
This is a workaround:
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Radiobutton1, Path=IsChecked}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Radiobutton1, Path=IsChecked}" Value="false">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding Designtime}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
then in Viewmodel:
public bool Designtime { get; set; }
public ViewModel()
{
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
{
Designtime = true;
}
}
And in the Window Tag
d:DataContext="{d:DesignInstance {x:Type local:ViewModel},IsDesignTimeCreatable=True}"
You can use the Blend namespace IsHidden attribute:
add the Blend namespace if missing: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
add the d:IsHidden="True" attribute on the element you want to hide at design time
Example:
<TextBox Style="{StaticResource text}" Text="test....." d:IsHidden="True"/>

How to use WPF Validation rules on a Listbox to enable a 'OK' button

I'm new with WPF and I have a problem. I want to enable a button only if en element of a Listbox is selected, otherwise it has to be disabled. I've tried with simple Validation Rule but it doesn't worked. Can anyone give me a hint? Ty
You don't use a ValidationRule to enable a Button but you could use a Button style with a trigger that binds to the SelectedItem property of the ListBox and sets the IsEnabled property of the Button to false if the SelectedItem property of the ListBox returns a null reference, e.g.:
<ListBox x:Name="lb">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
</ListBox>
<Button Content="Button">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=lb}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Ok, this works well ty. But I've to enable the button when 2 conditions are satisfied (a textbox not empty and an item of the listbox selected). How can i do this?
You could add another trigger:
<ListBox x:Name="lb">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
</ListBox>
<TextBox x:Name="txt" />
<Button Content="Button">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=lb}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=txt}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Set DataGridCell style depending on CheckBox Checked state in DataGridTemplateColumn

I have a DataGrid with data binding to DataTable with columns set to auto generate.
The first column has boolean data type replaced with DataGridTemplateColumn with CheckBox from DataTemplate. It all works fine as it is.
However, now I want to make the DataGridCell background to red when the CheckBox is not checked.
The problem is, I have no idea how to set CheckBox's parent DataGridCell style with IsChecked trigger.
WPF:
<Window.Resources>
<DataGridTemplateColumn x:Key="colSelect">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="chkBxSelect"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsChecked="{Binding Path=Select, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Click="chkBxSelect_Click">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox x:Name="chkBxSelectAll"
Content="Select"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsThreeState="True"
Click="chkBxSelectAll_Click"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.SelectAll}">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="DarkGray"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
</Window.Resources>
C# while DataGrid Column AutoGenerating:
DataGridTemplateColumn col = (DataGridTemplateColumn)Resources["colSelect"];
e.Column = col;
e.Column.IsReadOnly = false;
Update:
So far I have figured out it could be done using RelativeSource and AncestorType in Binding. However, still trying to make it work.
Well after struggling a lot and not even trying the most obvious solution. I found it. It was relatively very simple and easy.
Just added DataTrigger to DataGridCell style and all done, WPF is magic.
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="DarkGray"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</Trigger>
<DataTrigger Binding="{Binding Path=Select, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>

Better Binding for DataTrigger

I have a TextBlock and I want to set the property Visibility to Collapsed when the TextBlock has no text. I wonder me, for sure there should be a better way to check if the Lenght of the property Text is equal than 0.
<TextBlock Name="TextBlockHeader" Foreground="White" FontSize="18" FontWeight="Bold" Text="{Binding Header}" Margin="0,0,0,25">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=TextBlockHeader, Path=Text.Length}" Value="0">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Here I have to define a name for the TextBlock and I can reference it in the Datatrigger Binding="{Binding ElementName=TextBlockHeader, Path=Text.Length}"
But how can I achieve the same without having to define a name for the TextBlock?
You would usually use Triggers instead of DataTriggers, and compare the Text property to either null or an empty string.
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="Text" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
As the TextBlock class seems to coerce the Text property value to be non-null, it may be sufficient to have only the second Trigger for an empty string.

The attachable property Triggers was not found in Style

I have a RadTreeView and trying to use stye triggers for disabling few nodes:
<telerikNavigation:RadTreeView ItemTemplate="{StaticResource HierarchyItemsTreeItemTemplate}">
<telerikNavigation:RadTreeView.Style>
<Style TargetType="telerikNavigation:RadTreeView">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TreeViewItem}, Converter={StaticResource converter}}" Value="true">
<Setter Property="IsEnabled" Value="false"/>
</DataTrigger>
</Style.Triggers>
</Style>
</telerikNavigation:RadTreeView.Style>
</telerikNavigation:RadTreeView >
But this gives me error:
The attachable property Triggers was not found in Style
You don't seem to specify the property your Style should apply to which is the telerikNavigation:RadTreeView.Style. As of now you got a Style as the Content of the TreeView
Try:
<telerikNavigation:RadTreeView ItemTemplate="{StaticResource HierarchyItemsTreeItemTemplate}">
<telerikNavigation:RadTreeView.Style> <!-- Missing Line from original Code -->
<Style TargetType="telerikNavigation:RadTreeView">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType=TreeViewItem},
Converter={StaticResource converter}}"
Value="true">
<Setter Property="IsEnabled"
Value="false" />
</DataTrigger>
</Style.Triggers>
</Style>
</telerikNavigation:RadTreeView.Style> <!-- Missing Line from original Code -->
</telerikNavigation:RadTreeView>

Categories

Resources