<StackPanel>
<TextBox Text="" x:Name="input"/>
<Button Content="DataTrigger Before">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=input, Path=Text}" Value="1">
<Setter Property="Content" Value="Changed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
Style DataTrigger Setter in Button Content is invalid
Thanks
Your DataTrigger is not change the value of the Content property because you set it inside the Button declaration. So, once setted, it will never changed. To allow changing, you have to set the value inside the Style.
This will works (I've tried):
<StackPanel>
<TextBox Name="input"/>
<Button>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Content" Value="DataTrigger Before"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=input, Path=Text}" Value="1">
<Setter Property="Content" Value="Changed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
Related
I would like to change the image of an WPF Button on ListView empty, but I don't now which is the property I must set from the trigger.
<Style x:Key="DisableOnEmptyLvStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myListView, Path=Items.Count}" Value="0">
<Setter Property="IsEnabled" Value="False"/>
<!-- which button property I must set here? -->
</DataTrigger>
</Style.Triggers>
</Style>
<Button Style="{StaticResource DisableOnEmptyLvStyle}">
<Image Source="{StaticResource myImage}"/>
</Button>
Once ListView has items, then the image must change to the normal one.
Any ideas how to do this?
You should never set the Content directly using a Style, simply because the Style is instantiated once and potentially reused across multiple controls. The issue is that the value that you assign in the Setter for Content is also instantiated once and shared, but a control can only have a single parent in WPF.
What can go wrong? If you set or change the Content in a style and reference it for e.g. multiple Buttons you will see that only the last button shows the image. The first button gets its image set as Content, then the next button sets the image as Content and effectively removes the content of the first button.
There are two options that you can consider.
Create the images as resources and force each reference in XAML to get a new instance of the image by setting the x:Shared attribute to False.
When set to false, modifies WPF resource-retrieval behavior so that requests for the attributed resource create a new instance for each request instead of sharing the same instance for all requests.
<Window.Resources>
<!-- ...your image sources for "myImage" and "myImage". -->
<Image x:Key="myImageConrol" x:Shared="False" Source="{StaticResource myImage}"/>
<Image x:Key="myOtherImageConrol" x:Shared="False" Source="{StaticResource myImage}"/>
<Style x:Key="DisableOnEmptyLvStyle" TargetType="{x:Type Button}">
<Setter Property="Content" Value="{StaticResource myImageConrol}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myListView, Path=Items.Count}" Value="0">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Content" Value="{StaticResource myOtherImageConrol}">
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Button Style="{StaticResource DisableOnEmptyLvStyle}"/>
Create data templates and swap them out. This works because - as the name says - they are templates and its controls will be instantiated for each control they are applied to.
<Style x:Key="DisableOnEmptyLvStyle" TargetType="{x:Type Button}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource myImage}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myListView, Path=Items.Count}" Value="0">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{StaticResource myOtherImage}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Button Style="{StaticResource DisableOnEmptyLvStyle}"/>
Please try the following:
<Style x:Key="DisableOnEmptyLvStyle" TargetType="{x:Type Button}">
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource myImageAtLeastOne}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myListView, Path=Items.Count}" Value="0">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Content">
<Setter.Value>
<Image Source="{StaticResource myImageEmpty}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Button Style="{StaticResource DisableOnEmptyLvStyle}" />
I would like to use a DataTrigger to modify the opacity of my button.
<Button x:Name="StartTreatment"
Grid.Column="3"
Width="160"
Height="30"
Content="{x:Static resources:UserMessages.TrcsConsoleViewModel_LoadWfSequence_StartProcedure}"
IsEnabled="{Binding CanStartProcedure}"
Visibility="{Binding CanStartPatientTreatment, Converter={StaticResource BooleanToVisibility}}" >
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding CanStartProcedure}" Value="False">
<Setter Property="Opacity" Value="0.5"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I know that a Button has an Opacity you can set, and that DataTriggers must be used in a Style. However the compiler is reporting 'The member "Opacity" is not recognized or is not accessible.' What am I doing wrong?
You should add TargetType:
...
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding CanStartProcedure}" Value="False">
<Setter Property="Opacity" Value="0.5"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
...
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>
Is that possible to set the DataTrigger binding as below into style where the binding is repeatedly but the binding path is different?
<Button Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Background="{Binding Dyes[4].DyeBrush}">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource Dye}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Dyes[4].IsReferenceDye}" Value="True">
<Setter Property="Content" Value="R" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Background="{Binding Dyes[5].DyeBrush}">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource Dye}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Dyes[5].IsReferenceDye}" Value="True">
<Setter Property="Content" Value="R" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Make your style like
<Style x:Key="ButtonStyle" TargetType="Button" BasedOn="{StaticResource Dye}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsReferenceDye}" Value="True">
<Setter Property="Content" Value="R" />
</DataTrigger>
</Style.Triggers>
</Style>
and use it as
<Button Grid.Row="3" Grid.Column="1"
DataContext="{Binding Dyes[5]}"
Style="{StaticResource ButtonStyle}"
VerticalAlignment="Center" Background="{Binding Dyes[5].DyeBrush}"/>
Hope this helps.
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>