I'm working on a CustomControl in WPF. I want to Implement a CardControl. I have two Contents "Front" and "Back" and I want to flip between them.
But I can't define a Working Trigger in the Style to flip between the contents...
First I created a Custom Control, with DependencyProperties:
public class Card : Control {
#region initializer
static Card() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(Card), new FrameworkPropertyMetadata(typeof(Card)));
}
#endregion
#region dependencyProperties
public FrameworkElement CustomContent {
get { return (FrameworkElement)GetValue(CustomContentProperty); }
set { SetValue(CustomContentProperty, value); }
}
public static DependencyProperty CustomContentProperty =
DependencyProperty.Register(nameof(CustomContent), typeof(FrameworkElement), typeof(Card), new PropertyMetadata());
public FrameworkElement Front {
get { return (FrameworkElement)GetValue(FrontProperty); }
set { SetValue(FrontProperty, value); }
}
public static DependencyProperty FrontProperty =
DependencyProperty.Register(nameof(Front), typeof(FrameworkElement), typeof(Card), new PropertyMetadata());
public FrameworkElement Back {
get { return (FrameworkElement)GetValue(BackProperty); }
set { SetValue(BackProperty, value); }
}
public static DependencyProperty BackProperty =
DependencyProperty.Register(nameof(Back), typeof(FrameworkElement), typeof(Card), new PropertyMetadata());
public bool IsDetailed {
get { return (bool)GetValue(IsDetailedProperty); }
set { SetValue(IsDetailedProperty, value); }
}
public static readonly DependencyProperty IsDetailedProperty =
DependencyProperty.Register(nameof(IsDetailed), typeof(bool), typeof(Card), new PropertyMetadata(false));
public CornerRadius CornerRadius {
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius), typeof(Card));
#endregion
Then I defined the Style in Generic.xaml:
<Style TargetType="{x:Type local:Card}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Card}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:Card}}, Path=CustomContent,
Converter={StaticResource Debugger}, UpdateSourceTrigger=PropertyChanged}"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type local:Card}},
Path=isDetailed,
Converter={StaticResource Debugger}}"
Value="True">
<Setter Property="CustomContent"
Value="{Binding RelativeSource={RelativeSource
AncestorType={x:Type local:Card}},
Path=Back}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type local:Card}},
Path=isDetailed}"
Value="False">
<Setter Property="CustomContent"
Value="{Binding RelativeSource={RelativeSource
AncestorType={x:Type local:Card}},
Path=Front}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I Implemented a Simple CardControl for Test-Purposes with a Button, which flips the isDetailed state:
<StackPanel>
<CustomCharts:Card Name="TestCard">
<CustomCharts:Card.CustomContent>
<TextBlock Text="Hello World!"/>
</CustomCharts:Card.CustomContent>
<CustomCharts:Card.Front>
<TextBlock Text="Wow vordere sache!"/>
</CustomCharts:Card.Front>
<CustomCharts:Card.Back>
<TextBlock Text="Wow hintere sache!"/>
</CustomCharts:Card.Back>
</CustomCharts:Card>
<Button Click="Button_Click" Width="50" Height="20" Content="Test"/>
</StackPanel>
private void Button_Click( object sender, RoutedEventArgs e ) {
this.TestCard.IsDetailed= !this.TestCard.IsDetailed;
}
Any Help is apreciated, I'm stuck...
you can benefit a lot if declare Front and Back with object type, not FrameworkElement - mostly because it will allow easy bidnings. you can keep rich visual appearance if you add corresponding templates for those two properties.
public class Card : Control
{
static Card()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Card), new FrameworkPropertyMetadata(typeof(Card)));
}
public object Front
{
get { return (object)GetValue(FrontProperty); }
set { SetValue(FrontProperty, value); }
}
public static readonly DependencyProperty FrontProperty =
DependencyProperty.Register("Front", typeof(object), typeof(Card), new PropertyMetadata(null));
public DataTemplate FrontTemplate
{
get { return (DataTemplate)GetValue(FrontTemplateProperty); }
set { SetValue(FrontTemplateProperty, value); }
}
public static readonly DependencyProperty FrontTemplateProperty =
DependencyProperty.Register("FrontTemplate", typeof(DataTemplate), typeof(Card), new PropertyMetadata(null));
public object Back
{
get { return (object)GetValue(BackProperty); }
set { SetValue(BackProperty, value); }
}
public static readonly DependencyProperty BackProperty =
DependencyProperty.Register("Back", typeof(object), typeof(Card), new PropertyMetadata(null));
public DataTemplate BackTemplate
{
get { return (DataTemplate)GetValue(BackTemplateProperty); }
set { SetValue(BackTemplateProperty, value); }
}
public static readonly DependencyProperty BackTemplateProperty =
DependencyProperty.Register("BackTemplate", typeof(DataTemplate), typeof(Card), new PropertyMetadata(null));
public bool IsDetailed
{
get { return (bool)GetValue(IsDetailedProperty); }
set { SetValue(IsDetailedProperty, value); }
}
public static readonly DependencyProperty IsDetailedProperty =
DependencyProperty.Register(nameof(IsDetailed), typeof(bool), typeof(Card), new PropertyMetadata(false));
public CornerRadius CornerRadius
{
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius), typeof(Card), new PropertyMetadata(new CornerRadius(0)));
}
Use Trigger on IsDetailed property to flip Fron and Back:
<Style TargetType="{x:Type local:Card}">
<Setter Property="Background" Value="Khaki"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Card}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<ContentPresenter x:Name="presenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDetailed" Value="True">
<Setter TargetName="presenter" Property="Content"
Value="{Binding Front, RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="presenter" Property="ContentTemplate"
Value="{Binding FrontTemplate, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
<Trigger Property="IsDetailed" Value="False">
<Setter TargetName="presenter" Property="Content"
Value="{Binding Back, RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="presenter" Property="ContentTemplate"
Value="{Binding BackTemplate, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
use TemplateBindings inside Template, and RelativeSource TemplatedParent with normal Binding in Setters (TemplateBinding is not supported in Setter).
And here is two examples of usage - with and without binding:
<StackPanel DataContext="{x:Static sys:DateTime.Now}">
<CheckBox Name="chk_1"/>
<local:Card Front="Front"
Back="Back"
IsDetailed="{Binding IsChecked, ElementName=chk_1}"/>
<CheckBox Name="chk_2"/>
<local:Card Front="{Binding DayOfWeek}"
Back="{Binding TimeOfDay}"
IsDetailed="{Binding IsChecked, ElementName=chk_2}">
<local:Card.FrontTemplate>
<DataTemplate>
<TextBlock Foreground="Red" FontWeight="Bold" FontSize="20"
Text="{Binding}" TextDecorations="Underline"/>
</DataTemplate>
</local:Card.FrontTemplate>
<local:Card.BackTemplate>
<DataTemplate>
<TextBlock Foreground="Blue" FontWeight="Bold" FontSize="20"
Text="{Binding}" TextDecorations="Underline"/>
</DataTemplate>
</local:Card.BackTemplate>
</local:Card>
</StackPanel>
result:
Let's say I have the following class:
public class MyClass : System.Windows.FrameworkElement
{
public static readonly DependencyProperty HasFocusProperty = DependencyProperty.RegisterAttached("HasFocus", typeof(bool), typeof(MyClass), new PropertyMetadata(default(bool)));
public bool HasFocus
{
get => (bool)GetValue(HasFocusProperty);
set => SetValue(HasFocusProperty, value);
}
public System.Windows.Controls.TextBox TextBox { get; set; }
}
I want to change some UI properties of TextBox via XAML Template Trigger based on the property HasFocus, so I do the following:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:win="clr-namespace:System.Windows.Controls">
<Style TargetType="{x:Type win:TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type win:TextBox}">
<ControlTemplate.Triggers>
<Trigger Property="MyClass.HasFocus" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="Red" />
<Setter TargetName="Border" Property="BorderThickness" Value="2" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
However, the style is not applied when setting HasFocus = true.
Within the properties of TextBox, I can see that the trigger is registered. If I change <Trigger Property="MyClass.HasFocus" Value="True"> to <Trigger Property="MyClass.HasFocus" Value="False">, my style is applied initially. So I think my XAML definition is okay.
Any ideas how to solve this?
An element in a template that is applied to a TextBox cannot bind to a property of a MyClass, unless there is a MyClass element to bind to somewhere in the visual tree.
If you want to be able to set a custom HasFocus property of a TextBox, you should create an attached property:
public class FocusExtensions
{
public static readonly DependencyProperty SetHasFocusProperty = DependencyProperty.RegisterAttached(
"HasFocus",
typeof(bool),
typeof(FocusExtensions),
new FrameworkPropertyMetadata(false)
);
public static void SetHasFocus(TextBox element, bool value)
{
element.SetValue(SetHasFocusProperty, value);
}
public static bool GetHasFocus(TextBox element)
{
return (bool)element.GetValue(SetHasFocusProperty);
}
}
It can be set for any TextBox element:
<TextBox local:FocusExtensions.HasFocus="True">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="local:FocusExtensions.HasFocus" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="2" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
I have a StackPanel with a few buttons. I want to change the color of a button when clicked and reset it to the original when another button in StackPanel is clicked. Is it possible with a single style applied on StackPanel or I have to create Style for each button? If yes then how.
Here is the code of Style applied to StackPanel but this changes the color of the button but does not reset it on clicking another button.
<Style TargetType="StackPanel" x:Key="GlobalStackPanelStyle" BasedOn="{StaticResource FlatStackPanel}">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Button.Background" Value="Blue"/>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" To="Green"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
Sorry for the delayed response. Here are the steps that you can follow to get the required output.
Assuming you are following MVVM design pattern.
Create buttons in .xaml and bind command to each button as shown below,
<Button Height="32" Width="180" Grid.Column="1" Content="Button 1"
Command="{Binding ClickCommand}" CommandParameter="Button 1">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsButton1Active}" Value="True">
<Setter Property="Background" Value="Green" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
<DataTrigger Binding="{Binding IsButton1Active}" Value="False">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Height="32" Width="180" Grid.Column="2" Content="Button 2"
Margin="5,0,0,0"
Command="{Binding ClickCommand}" CommandParameter="Button 2">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsButton2Active}" Value="True">
<Setter Property="Background" Value="Green" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
<DataTrigger Binding="{Binding IsButton2Active}" Value="False">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Note: You can add how many buttons you want to add to above xaml.
Create 2 boolean properties and set the values of those boolean properties from your ClickCommand method.
private bool isButton1Active;
private bool isButton2Active;
public bool IsButton1Active
{
get { return isButton1Active; }
set { isButton1Active = value; OnPropertyChanged(); }
}
public bool IsButton2Active
{
get { return isButton2Active; }
set { isButton2Active = value; OnPropertyChanged(); }
}
Here is code for command - Add it in your ViewModel
private UICommand _clickCommand;
public UICommand ClickCommand
{
get { return _clickCommand; }
}
Write below statement in your view model constructor
public YourViewModelConstructor()
{
_clickCommand = new UICommand(OnClick);
}
Here is the method that is bound to ClickCommand
private void OnClick(object parameter)
{
switch(parameter.ToString())
{
case "Button 1":
IsButton1Active = true;
IsButton2Active = false;
break;
case "Button 2":
IsButton2Active = true;
IsButton1Active = false;
break;
}
}
Here is the code for my UICommand class
public class UICommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<bool> _canExecute;
public UICommand(Action<object> onExecuteMethod, Func<bool> onCanExecuteMethod =
null)
{
_execute = onExecuteMethod;
_canExecute = onCanExecuteMethod;
}
public bool IsCanExecute { get; set; }
#region ICommand Members
public event EventHandler CanExecuteChanged
{
add { if (_canExecute != null) CommandManager.RequerySuggested += value; }
remove { if (_canExecute != null) CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
public bool CanExecute(object parameter)
{
IsCanExecute = (_canExecute == null || _canExecute());
return IsCanExecute;
}
#endregion
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
}
I assume you know on how to setting datacontext to your window.
This examples gives you an idea on how to achieve functionality by creating some properties created in your ViewModel and bind a command in your View to ViewModel Command property and invoke click command by passing Command Parameter.
Still have any doubts after implementing the solution, kindly let us know.
In my application I have a very large DataGrid with several DataGridTemplateColumns. In the resources of the DataGrid there is a style for the DataGridRows. This style looks like:
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsEditing}" Value="True">
<Setter Property="AttachedProperties:DataGridExtensions.FocusOnEditingColumn" Value="{Binding IsEditing}"/>
</DataTrigger>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
In my ViewModel I'm subscribed to the PropertyChanged-Event of the DataObjects which are contained in the ItemsSource of the DataGrid. So if the PropertyChanged-Event is called and the propertyname equals "IsEdit" I'll do some validations for all rows in the DataGrid. Therfor I'm using the following method:
private void CheckConsistence()
{
foreach (Module module in SelectedGroup.Modules)
{
string currentTarget = ResolveTargetPath(module);
foreach (Module toCompare in SelectedGroup.Modules.Except(new[] { module }))
{
string toCompareTarget = ResolveTargetPath(toCompare);
if (string.Compare(currentTarget, toCompareTarget, StringComparison.InvariantCultureIgnoreCase) == 0)
{
module.IsInvalid = true;
ValidationAdvices.Add(new ValidationAdvice("Duplicated path"));
}
}
}
}
If the IsInvalid-Property in the Module-Object is set to true I change the Error-Object. A part of the Module-Object looks like:
public class Module : INotifyPropertyChanged, IDataErrorInfo
{
private bool isEditing;
public bool IsEditing
{
get { return isEditing; }
set
{
isEditing = value;
OnPropertyChanged(() => IsEditing);
}
}
private bool isInvalid;
public bool IsInvalid
{
get { return isInvalid; }
set
{
isInvalid = value;
if (isInvalid)
{
error = "Error";
}
else
{
error = null;
}
OnPropertyChanged(() => IsInvalid);
OnPropertyChanged(() => Error);
}
}
public string this[string columnName]
{
get { return string.Empty; }
}
private string error;
public string Error
{
get { return error; }
}
}
My DataGrid has a RowValidationErrorTemplate which looks like:
<ControlTemplate x:Key="RowErrorTemplate" TargetType="Control" x:Shared="False">
<Grid ClipToBounds="False" Panel.ZIndex="10000">
<AdornedElementPlaceholder Name="adornedElement"/>
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Width="16" Height="16"
Source="pack://application:,,,/MyApp.UI.Resources;component/Graphics/Error_16x16.png"
ToolTipService.IsEnabled="True"
ToolTipService.ShowOnDisabled="True"
ToolTip="{Binding Converter={converters:ModuleValidationErrorConverter}}"/>
</Grid>
</ControlTemplate>
My problem is now if two rows have the same path both rows should be displayed as error-rows. But only one row will get the errortemplate and the red-background defined in the Style for the DataGridRow. The call of ValidationAdvices.Add(new ValidationAdvice("Duplicated path")); is done for each row. What do I have to do so that every row gets the validationerrortemplate?
I also have set the DataGrid.RowValidationRules like:
<DataGrid.RowValidationRules>
<DataErrorValidationRule ValidatesOnTargetUpdated="True" ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
recently I've tried to make label style which would allow to display image or textblock depending on property being set or not. I've bound proper objects to labels' DataContext and prepared reusable style for these labels. Default content is textblock with Name as its text but if IsIconSet property is true, then content would change into image with corresponding IconPath as source.
Similar approach works perfectly with label's properties like background or cursor but in described scenario it breaks up when IsIconSet has the same value in both instances. Then it displays nothing for first label and correct textblock/image for second label.
I've tried to attach converter to Name and IconPath bindings in style in order to check what value is being passed but it seems that it isn't even invoked on first label.
Has anyone managed to do something similar? Am I missing something fundamental? Or maybe there is another approach for such behaviour?
Any help will be appreciate.
Simplified code:
MainWindow
<StackPanel DataContext="{Binding First}">
<Label Style="{StaticResource LabelStyle}" />
</StackPanel>
<StackPanel DataContext="{Binding Second}">
<Label Style="{StaticResource LabelStyle}" />
</StackPanel>
Style
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="{Binding Name}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIconSet}" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding IconPath}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Classes
public class ViewModel : INotifyPropertyChanged
{
private LabelClass _first;
private LabelClass _second;
public LabelClass First
{
get => _first;
set
{
_first = value;
OnPropertyChanged();
}
}
public LabelClass Second
{
get => _second;
set
{
_second = value;
OnPropertyChanged();
}
}
public ViewModel()
{
First = new LabelClass("First", "Resources/first.png");
Second = new LabelClass("Second", "Resources/second.png");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class LabelClass : INotifyPropertyChanged
{
private string _name;
private string _iconPath;
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public string IconPath
{
get => _iconPath;
set
{
_iconPath = value;
OnPropertyChanged();
OnPropertyChanged("IsIconSet");
}
}
public bool IsIconSet => !string.IsNullOrEmpty(IconPath);
public LabelClass(string name, string iconPath = null)
{
Name = name;
IconPath = iconPath;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
LabelStyle can be used by multiple Labels, but TextBlock and Image from Content setter are created just once, there is only one instance for all labels, but it cannot be displayed in multiple places. so it is displayed in only one.
to fix the issue use ContentTemplate, like shown below.
<Setter Property="Content" Value="{Binding}"/> line means that entire DataContext is considered as Label Content. Is is necessary for bindings in ContentTemplate
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Content" Value="{Binding}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIconSet}" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{Binding IconPath}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
alternatively, convert TextBlock and Image to non-shared resources:
<Image Source="{Binding IconPath}" x:Key="Img" x:Shared="False"/>
<TextBlock Text="{Binding Name}" x:Key="Txt" x:Shared="False"/>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Content" Value="{StaticResource Txt}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIconSet}" Value="True">
<Setter Property="Content" Value="{StaticResource Img}"/>
</DataTrigger>
</Style.Triggers>
</Style>