DataTrigger for IconTemplate in RadWindow - c#

I have a WPF application and I use Telerik.
I'm trying to set the Icon Template so that it has a default value and only on a certain condition will it bind the image source:
<telerik:RadWindow.Resources>
<Style x:Key="CustomIconStyle" TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsConditionMet, ElementName=MyWindow, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="Source" Value="{Binding Path=IconImageSource, ElementName=MyWindow, UpdateSourceTrigger=PropertyChanged}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</telerik:RadWindow.Resources>
<telerik:RadWindow.IconTemplate>
<DataTemplate>
<Image Style="{StaticResource CustomIconStyle}" Source="/MyAssembly;Component/Resources/myIcon.ico" Height="16" Margin="0,0,5,0"/>
</DataTemplate>
</telerik:RadWindow.IconTemplate>
For some reason it always show the default icon.
I would also like to mention that I did implement the property changed - and I copied the same style just to a control inside the window and not in the template and it worked - so the problem isn't with the property changed
Any ideas?

You can use Triggers like that :
<telerik:RadWindow.Resources>
<Style TargetType="Image" x:Key="Style1">
<Setter Property="Source" Value="default.ico"/>
<Style.Triggers>
<DataTrigger Binding="{Binding MyCondition}" Value="true">
<Setter Property="Source" Value="custom.ico"/>
</DataTrigger>
</Style.Triggers>
</Style>
</telerik:RadWindow.Resources>
<telerik:RadWindow.IconTemplate>
<DataTemplate>
<Image Style="{StaticResource Style1}" Height="16" Margin="0,0,5,0"/>
</DataTemplate>
</telerik:RadWindow.IconTemplate>

So the problem was that once the RadWindow was loaded it didn't change the Icon.
The solution:
<telerik:RadWindow.IconTemplate>
<DataTemplate>
<Image Height="16" Margin="0,0,5,0">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/MyAssembly;Component/Resources/myIcon.ico" />
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding Path=IsConditionMet, ElementName=MyWindow}">
<Setter Property="Source" Value="{Binding Path=IconImageSource, ElementName=MyWindow}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</telerik:RadWindow.IconTemplate>
But the trick is to give the correct value of IsConditionMet in the windows constructor before the load.
Thanks for the help everyone.

Related

ContentStringFormat never changes by Setter Property in DataTrigger

In my user control I want to have label displaying Text from resource depending on viewmodel property Location value and with different format.
I implemented it by defining DataTrigger for each Location value
<Style x:Key="LocationValueHelper" TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding Location}" Value="HomeViewModel">
<Setter Property="Content" Value="" />
<Setter Property="ContentStringFormat" Value="{}{0}???"/>
</DataTrigger>
<DataTrigger Binding="{Binding Location}" Value="FirstViewModel">
<Setter Property="ContentStringFormat" Value="{}{0}+++"/>
<Setter Property="Content" Value="{localization:LanguageResource ResourceKey=First}" />
</DataTrigger>
<DataTrigger Binding="{Binding Location}" Value="SecondViewModel">
<Setter Property="ContentStringFormat" Value="{}{0}---"/>
<Setter Property="Content" Value="{localization:LanguageResource ResourceKey=Second}" />
</DataTrigger>
<DataTrigger Binding="{Binding Location}" Value="ThirdViewModel">
<Setter Property="ContentStringFormat" Value="{}{0}***"/>
<Setter Property="Content" Value="{localization:LanguageResource ResourceKey=Third}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Label Foreground="White" HorizontalAlignment="Center" FontSize="40" Style="{StaticResource LocationValueHelper}" />
The problem is that format never changes from the first one (???) - HomeViewModel selected first - although text changing works.
I have
Home???
First???
Second???
Third???
instead of
Home???
First+++
Second---
Third***
There are a lot of discussions, using Labels and ContentStringFormat does not work like expected or desired:
WPF StringFormat on Label Content
StringFormat VS ContentStringFormat
...
The reason seems to be the template based implementation under the hood, since the content also could contain other data than strings. To solve your problem, my proposal is to use a TextBlock, which works quite smooth like this:
<StackPanel>
<CheckBox IsChecked="{Binding MyFlag}"/>
<TextBlock HorizontalAlignment="Center" FontSize="40">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding MyFlag}" Value="False">
<Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}+++'}" />
</DataTrigger>
<DataTrigger Binding="{Binding MyFlag}" Value="True">
<Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}???'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>

Reusing style trigger in wpf

I have done some research on this but failed to find out on how to reuse the style trigger.
I have style trigger set on Label and I am using Data trigger to set content. I have multiple labels in same view and also in different view. The Data bound is of same type except its different property of same data context.
Consider following 2 different labels where I need to display performance of 2 person - PersonA and PersonB. The value displayed for both the labels will be based on Performance format selected.
<Label Grid.Row="5" Grid.Column="9"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center">
<Label.Style>
<Style BasedOn="{StaticResource SomeGlobalStaticStyle}" TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="Fractional">
<Setter Property="Content" Value="{Binding DataModel.PersonA.Performance.Value.Fractional}" />
</DataTrigger>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="Decimal">
<Setter Property="Content" Value="{Binding DataModel.PersonA.Performance.Value.Decimal}" />
</DataTrigger>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="US">
<Setter Property="Content" Value="{DataModel.PersonA.Performance.Value.US}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
<Label Grid.Row="6" Grid.Column="9"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center">
<Label.Style>
<Style BasedOn="{StaticResource SomeGlobalStaticStyle}" TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="Fractional">
<Setter Property="Content" Value="{Binding DataModel.PersonB.Performance.Value.Fractional}" />
</DataTrigger>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="Decimal">
<Setter Property="Content" Value="{Binding DataModel.PersonB.Performance.Value.Decimal}" />
</DataTrigger>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="US">
<Setter Property="Content" Value="{DataModel.PersonB.Performance.Value.US}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
If you see, the only difference is the first trigger takes PersonA and the second trigger takes PersonB. I have 10 instances of such label spread in same and multiple views. Is there is way I can define this trigger once in Resources and bind whatever data I want to from each Label.
Looking forward for the solution.
Regards,
Abdyax
configurate setters to obtain values not from Label DataContext, but another Label property - Tag
<Style BasedOn="{StaticResource SomeGlobalStaticStyle}" TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="Fractional">
<Setter Property="Content" Value="{Binding Tag.Performance.Value.Fractional, RelativeSource={RelativeSource Self}}}" />
</DataTrigger>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="Decimal">
<Setter Property="Content" Value="{Binding Tag.Performance.Value.Decimal, RelativeSource={RelativeSource Self}}" />
</DataTrigger>
<DataTrigger Binding="{Binding PersonModel.PerformanceFormat}" Value="US">
<Setter Property="Content" Value="{Binding Tag.Performance.Value.US, RelativeSource={RelativeSource Self}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
and bind labels Tag to different properties:
<Label Grid.Row="5" Grid.Column="9"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center" Tag="{Binding DataModel.PersonA}"/>
<Label Grid.Row="6" Grid.Column="9"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center" Tag="{Binding DataModel.PersonB}"/>
both labels should pick our default style for TargetType="Label" with triggers
Is there is way I can define this trigger once in Resources and bind whatever data I want to from each Label.
Short answer: No, I am afraid not. You cannot replace the Value of a Setter but reuse the rest of the Style in XAML.
You could create the styles programmatically using the XamlReader.Parse method. Then you can simply replace the "PersonA" with "PersonB" in the string that you pass to the method.
But there is no way to do this generally in pure XAML.

Change image of button on click of combobox

I am trying something like this: as my form load I have one image on button (this part work fine) and one check box. When I check checkbox, the image of button should change. I have attached my xaml code with this. Please go through it and suggest changes.
<CheckBox Name="checkbox" Margin="141,148,336,147"/>
<Button Foreground="Black" Height="50" Margin="238,206,179,64">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal">
<Image>
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="Images/cancel_16.ico" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,
RelativeSource={RelativeSource AncestorType=
{x:Type Button}}}" Value="True">
<Setter Property="Image.Source"
Value="Images/cancel_16grayscale.ico" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ContentPresenter Content="{TemplateBinding Content}"
Margin="5,0,0,0" />
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
Just Remove the RelativeSource and add UpdateSourceTrigger Like this in your style
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,UpdateSourceTrigger=PropertyChanged}"
Value="True">
<Setter Property="Image.Source"
Value="Back_jeans.jpg" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,UpdateSourceTrigger=PropertyChanged}"
Value="False">
<Setter Property="Image.Source"
Value="Blue_Front_Jeans.jpg" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>

DataTrigger on an Image that should change the Image.Source property does not work

I reproduced this question/answer as given below:
<Button Command="Play" ToolTip="Execute Macro">
<Image DataContext="{Binding ElementName=UserControlMacroEdit}" Source="/ParametricStudySharedGui;component/Image/arrowRight32x32.png" Height="24" Width="24">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMacroRunning, Converter={StaticResource FakeTransparentConverter}, Mode=OneWay}" Value="True">
<DataTrigger.Setters>
<Setter Property="Source" Value="/ParametricStudySharedGui;component/Image/Run24.png"></Setter>
<Setter Property="Opacity" Value=".5"></Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
However, there is a strange behavior.
The "Opacity" changed but the image itself stay the same. It look like that I can't modify the Image.Source from a DataTrigger. Why?
Your original code does not work because of how dependency properties are handled. In particular, since they can be set from multiple places, WPF implements the idea of "priority" for such properties. "Locally set" properties (i.e. where they are set as part of the declaration of the element in XAML) have higher precedence over any setters found in styles.
Please see Dependency Property Value Precedence for more details.
You can work around the problem by initializing the Source property in the Style itself, rather than as part of the Image declaration:
<Image DataContext="{Binding ElementName=UserControlMacroEdit}" Height="24" Width="24">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/ParametricStudySharedGui;component/Image/arrowRight32x32.png"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMacroRunning, Converter={StaticResource FakeTransparentConverter}, Mode=OneWay}" Value="True">
<DataTrigger.Setters>
<Setter Property="Source" Value="/ParametricStudySharedGui;component/Image/Run24.png"></Setter>
<Setter Property="Opacity" Value=".5"></Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>

How to Bind an another Control on the Setter Value Property by using a Trigger?

i've a little Problem with the Databinding in WPF an hope you can help me.
I want to bind the SelectedDate Parameter of a DatePicker on a TextBlock, but only when a CheckBox is checked. The CheckBox and the TextBlock are in a DataView, the DatePicker is outside.
In the Moment i try to use it with a Trigger an set the Binding in the Value-Property in the Setter Part.
<TextBlock Text="">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=StandartPitBis, Path=SelectedDate, StringFormat='dd.MM.yyyy'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
But this will not works. Has anywone a Tipp what i can do?
Here is the Code-Parts there i'm using:
Inside the GridView
The CheckBox
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Content="" x:Name="check_Anlage" IsChecked="{Binding Path=IsChecked}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The TextBlock
<TextBlock Text="">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=StandartPitBis, Path=SelectedDate, StringFormat='dd.MM.yyyy'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Outside the GridView
The DatePicker
<DatePicker Grid.Column="1" Margin="0,5,0,5" SelectedDate="{x:Static sys:DateTime.Now}" x:Name="StandartPitVon" />
What i want to make is, that the SelectedDate from the DatePicker is shown in the TextBlock, but only when the CheckBox is Checked.
Thanks a lot
So. I've found the Problem. The Problem is, when a Property is set in the Object self, then it can't be overridet. When you need a Default-Value and a Trigger, then you must define the Default-Value in the Style too.
Example:
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{x:Null}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=StandartPitVon, Path=SelectedDate, StringFormat='dd.MM.yyyy'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

Categories