Can't update textbox property using DataBinding - wpf

I have a custom window which have two depencency properties: Boolean? ValidationStatus, and string ValidationMessage. Binding these properties works fine but trigger doesn't seem to be triggered when these values change. What am I doing wrong?
<TextBlock x:Name="validationTextBox"
Grid.Row="1"
Grid.ColumnSpan="2"
Text="{Binding ElementName=_this, Path=ValidationMessage}"
TextAlignment="Center"
Background="Green">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Value="False" Binding="{Binding ElementName=_this, Path=ValidationStatus}">
<Setter Property="Panel.Background" Value="Red"/>
<Setter Property="TextBox.Text" Value="Outer checkbox is not checked"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

Style Setters do not override local attribute settings. Therefore the data trigger's values are being ignored because you have specified the Text and Background properties on the TextBlock. To fix the problem set the default values of these properties in the style as shown in the following code:
<TextBlock x:Name="validationTextBox"
Grid.Row="1"
Grid.ColumnSpan="2"
TextAlignment="Center">
<TextBlock.Style>
<Style>
<Setter Property="TextBox.Text" Value="{Binding ElementName=_this, Path=ValidationMessage}"/>
<Setter Property="TextBox.Background" Value="Green"/>
<Style.Triggers>
<DataTrigger Value="False" Binding="{Binding ElementName=_this, Path=ValidationStatus}">
<Setter Property="TextBox.Background" Value="Red"/>
<Setter Property="TextBox.Text" Value="Outer checkbox is not checked"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

Related

checkbox disabling and enabling in wpf

IN my below code i have 2 check boxes chkQAReviewMandatory and chkIsAnsMandatory. My requirement is when i check the chkQAReviewMandatory checkbox then automatically i need to checkbox chkIsAnsMandatory is checked and disabled, If chkQAReviewMandatory is not checked then uncheck the chkIsAnsMandatory and also enable it.
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" Margin="5,15,5,0">
<CheckBox x:Name="chkQAReviewMandatory" Content="QA Review Mandatory" Grid.Row="1" Grid.Column="0" Margin="0,5,0,0"
IsChecked="{Binding IsQAReviewMandatory}"/>
<StackPanel Orientation="Horizontal" Margin="20,0,0,0">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=chkQAReviewMandatory, Path=IsChecked}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Label x:Name="lblMax" Content="QA Max Point" Height="20" VerticalAlignment="Center" Margin="0,5,5,0"></Label>
<local:NumericTextBox Width="50"
MaxLength="1"
Height="25"
VerticalAlignment="Top"
Text="{Binding MaximumQAPoints}" />
</StackPanel>
</StackPanel>
<CheckBox Content="Is Answer Mandatory"
Grid.Row="2"
HorizontalAlignment="Left"
Margin="5,12,0,0"
IsChecked="{Binding IsAnswerMandatory}" >
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=chkQAReviewMandatory,Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="True"/>
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=chkQAReviewMandatory,Path=IsChecked}" Value="False">
<Setter Property="IsChecked" Value="False"/>
<Setter Property="IsEnabled" Value="True"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
There are two ways:
For one control, bind the IsEnabled and IsChecked properties to properties in the ViewModel. On the other control, bind the IsEnabled to the IsChecked. This means that if one checkbox gets ticked, the other one becomes enabled.
You can not only bind to properties in code, you can bind to properties on other controls. Set the name of the control using x:Name, then you can bind to any property on that control.
As for the details on how to do this, use my answer to find keywords to Google. Good luck!

WPF DataTrigger not working On ComboBox?

I've got the following pure XAML:
<DockPanel>
<ComboBox Name="combo" Height="24" Width="60">
<Border Background="Gray" Padding="20,10">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combo, Path=IsDropDownOpen}" Value="True">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</ComboBox>
<TextBlock Text="{Binding ElementName=combo, Path=IsDropDownOpen}"></TextBlock>
</DockPanel>
I would expect the datatrigger to change the background colour of the border object to red as soon as the combobox is opened, but instead nothing happens.
Since you have set the background property directly on the ComboBox the trigger is not going to override that value.
This behavior is explained on MSDN.
You have to set it in the style instead like this:
<Border Padding="20,10">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Gray" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combo, Path=IsDropDownOpen}" Value="True">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>

WPF Showing / Hiding a control with triggers

I'm new to WPF and I trying to create xaml logic to show / hide a control based on the value of the AllowMiscTitle on the ViewModel. The xaml consist of two fields a combobox of the standard tiles ("Mr", "Mrs", ..., "Other") when "Other" is selected I want the textbox to display.
I've created the follow xaml:
<DockPanel Validation.Error="Validation_Error" HorizontalAlignment="Stretch">
<ComboBox ItemsSource="{Binding Path=Titles, Mode=OneTime}"
Text="{Binding Path=Title}"/>
<TextBox x:Name="TxtBxTitle" Margin="5,5" Visibility="Visible">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AllowMiscTitle}" Value="false">
<Setter Property="TextBox.Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</DockPanel>
That Trigger won't work because you have set Visibility property explicitly in TextBox
Do it like this:
<TextBox x:Name="TxtBxTitle" Margin="5,5">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AllowMiscTitle}" Value="false">
<Setter Property="TextBox.Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
The reason for this is Dependency property value precedence.
There is a
<BooleanToVisibilityConverter x:Key="BoolToVis"></BooleanToVisibilityConverter>
You can use it as following
<TextBox Visibility="{Binding YourPropertyName, Converter={StaticResource BoolToVis}}"></TextBox>
If I got your question right:-
If your selected value is binded to some property in the ViewModel like:-
private string _GenderType;
public string GenderType
{
get
{
return _GenderType;
}
set
{
_GenderType= value;
RaisePropertyChanged("GenderType");
In xaml:-
<TextBox.Style>
<Style>
<Setter Property="TextBox.Visibility" value="Hidden"/>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=GenderType,ElementName=Combo1}" Value="Other">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>

Setting different styles for Dual level grouping with DataTrigger

I have a dual level grouping and thought I could define different styles with DataTriggers.
Thinking that GroupStyles.HeaderTemplate would bind to CollectionViewGroup I tried DataBinding to IsBottomLevel property.
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock x:Name="GroupName"
Text="{Binding Path=Name}"
Foreground="Red" />
<DataTemplate.Triggers>
<DataTrigger Binding="IsBottomLevel" Value="True" >
<Setter TargetName="GroupName" Property="Foreground" Value="Blue" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
Can I get this to work somehow?
Define your trigger in the Style of the TextBlock itself, TargetName normally is for ControlTemplates, then you can just drop that.
This is not a binding:
Binding="IsBottomLevel"
You should replace it with the following of course:
Binding="{Binding IsBottomLevel}"
<TextBlock Text="{Binding Name}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsBottomLevel}" Value="True">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
If you set the red Foreground directly in the TextBlock declaration the trigger will have no effect due to precedence.

WPF Listbox - Empty List Display Message

Can anyone suggest the best way to display a Textblock (with a text such as "List Empty") so that it's visibility is bound to the Items.Count.
I have tried the following code and can't get it to work, so think that I must be doing it wrong.
<ListBox x:Name="lstItems"
ItemsSource="{Binding ListItems}">
</ListBox>
<TextBlock Margin="4" FontStyle="Italic" FontSize="12" Text="List is empty" Visibility="Collapsed">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lstItems, Path=Items.Count}" Value="0">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
The problem in your code is that setting the value of Visibility in the text block itself has higher priority than setting it in the style. So, even when the trigger occurs, the setting inside the trigger has no effect. Change the XAML to:
<TextBlock Margin="4" FontStyle="Italic" FontSize="12" Text="List is empty" >
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lstItems, Path=Items.Count}" Value="0">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Where the setting of Visibility is all in the style and it works (at least in my demo project).

Resources