Fire trigger in UserControl based on DependencyProperty - wpf

have a very easy question, but it seems I could not find the answer on the Internet for it. Possibly because I am not looking in the right places.
I have a user control with a DependencyProperty of a custom enum type.
In XAML I would like to Show/Hide elements based on the value of the enum type. I tried to do this with DataTriggers but I fail to get it working.
<UserControl x:Class="WpfApplication1.DisplayIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="50"
x:Name="control">
<UserControl.Resources>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Value="Ellipse" Binding="{Binding MyIconType, ElementName=control}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="Rectangle">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Value="Rectangle" Binding="{Binding MyIconType, ElementName=control}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<Ellipse x:Name="el1" Fill="Red" Width="30" Height="30" />
<Rectangle x:Name="el2" Fill="Green" Width="20" Height="20" />
<TextBlock Text="{Binding MyIconType, ElementName=control}" Margin="0,40,0,0"/>
</Grid></UserControl>
And my code behind looks like this:
public enum IconType
{
Ellipse,
Rectangle
}
public partial class DisplayIcon : UserControl
{
public DisplayIcon()
{
InitializeComponent();
}
public IconType MyIconType
{
get { return (IconType)GetValue(MyIconTypeProperty); }
set { SetValue(MyIconTypeProperty, value); }
}
// Using a DependencyProperty as the backing store for MyIconType. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyIconTypeProperty =
DependencyProperty.Register("MyIconType", typeof(IconType), typeof(DisplayIcon), new PropertyMetadata(IconType.Ellipse));
}
Can someone help me?
Thanks,
Jim

You can create a Style for each element and define the Triggers there:
<UserControl x:Class="WpfApplication1.DisplayIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="50"
x:Name="control">
<UserControl.Resources>
<Style TargetType="Ellipse">
<Style.Triggers>
<DataTrigger Value="Rectangle" Binding="{Binding MyIconType, ElementName=control}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Value="Ellipse" Binding="{Binding MyIconType, ElementName=control}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<Ellipse x:Name="el1" Fill="Red" Width="20" Height="20"/>
<Rectangle Grid.Row="1" x:Name="el2" Fill="Green" Width="20" Height="20"/>
</Grid>
EDIT:
Infact it would probably make more sense to invert the Visibility logic. That way you can add shapes without needing to modify the code:
<UserControl x:Class="WpfApplication1.DisplayIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="50"
x:Name="control">
<UserControl.Resources>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Value="Ellipse" Binding="{Binding MyIconType, ElementName=control}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="Rectangle">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Value="Rectangle" Binding="{Binding MyIconType, ElementName=control}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<Ellipse x:Name="el1" Fill="Red" Width="20" Height="20"/>
<Rectangle x:Name="el2" Fill="Green" Width="20" Height="20"/>
</Grid>

Related

On button hover, enable ResizeMode

I am trying to make window frame appear when user hovers "mybutton". This should work but for some reason it is not. What am I missing?
<Window x:Class="test2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowStyle="None" Loaded="ShellWindow_SourceInitialized" x:Name="mywindow">
<Window.Resources>
<Style TargetType="{x:Type Window}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="True">
<Setter Property="ResizeMode" Value="CanResize" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="False">
<Setter Property="ResizeMode" Value="NoResize" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Name="mygrid" Loaded="Grid_Loaded">
<Button Name="mybutton" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"/>
</Grid>
(In case you are wondering what those "Loaded" functions are, they remove chrome while keeping the shadow and allowtransparency=false
http://marcin.floryan.pl/blog/2010/08/wpf-drop-shadow-with-windows-dwm-api)
At the end it will not be button but will react on whole window border (I can not find better way to enable resizing while removing all chrome)
In the style TargetType should be MainWindow
<Style TargetType="{x:Type local:MainWindow}">
where local has to be mapped to your namespace:
xmlns:local="clr-namespace:test2"
myButton is defined after style. XAML parser is not that smart. User the following XAML to get your intended behavior:
<Window x:Class="test2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowStyle="None" Loaded="ShellWindow_SourceInitialized" x:Name="mywindow">
<Grid Name="mygrid" Loaded="Grid_Loaded" >
<Button Name="mybutton" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"/>
</Grid>
<Window.Style>
<Style TargetType="{x:Type Window}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="True">
<Setter Property="ResizeMode" Value="CanResize" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="False">
<Setter Property="ResizeMode" Value="NoResize" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>
</Window>

Set Datacontext of a control to a property

I am trying to create a style for a textblock to create a highlight effect. This style will be used on a number of TextBlocks, each bound to a different property. The datacontext for my main control is set in code behind:
this.DataContext = dataobject;
I can create one textblock with a working binding like this:
<TextBlock Text="Field1">
<TextBlock.Style>
<Style x:Key="HighlightStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=.}" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
<TextBlock>
But I need to change the binding so that the style can be used on different TextBlocks. Something like:
<Style x:Key="HighlightStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=.}" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBlock Text="Field1" DataContext="{Binding Path=BooleanProperty1}" Style="{StaticResource HighlightStyle}"/>
<TextBlock Text="Field2" DataContext="{Binding Path=BooleanProperty2}" Style="{StaticResource HighlightStyle}"/>
When I try this, changing the properties does nothing to highlight the textblock. Is there a way to accomplish this?
Could always abuse the tag property.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Tag" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Field1" Grid.Row="0" Tag="{Binding Field1}"/>
<TextBlock Text="Field2" Grid.Row="1" Tag="{Binding Field2}"/>
</Grid>
</Window>
or if you're feeling adventurous you could create an attached dependency property and pass that over.
public class TextBlockExtender : DependencyObject
{
public static string GetMyDataField(DependencyObject obj)
{
return (string)obj.GetValue(MyDataFieldProperty);
}
public static void SetMyDataField(DependencyObject obj, string value)
{
obj.SetValue(MyDataFieldProperty, value);
}
public static readonly DependencyProperty MyDataFieldProperty =
DependencyProperty.RegisterAttached("MyDataField", typeof(string), typeof(TextBlockExtender), new PropertyMetadata(null));
}
used with XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="local:TextBlockExtender.MyDataField" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Field1" Grid.Row="0" local:TextBlockExtender.MyDataField="{Binding Field1}"/>
<TextBlock Text="Field2" Grid.Row="1" local:TextBlockExtender.MyDataField="{Binding Field2}"/>
</Grid>
</Window>

Trying to bind to enum inside of DataTrigger, why isn't it working?

I would expect my Ellipse to be Red right now.
<UserControl x:Class="BenchmarkPlus.PMT.UI.Views.NotificationIndicator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:Models="clr-namespace:BenchmarkPlus.PMT.UI.Models"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
x:Name="root"
DataContext="{x:Static Models:NotificationType.Error}">
<Grid>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill"
Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding}"
Value="{x:Static Models:NotificationType.Info}">
<Setter Property="Fill"
Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding}"
Value="{x:Static Models:NotificationType.Error}">
<Setter Property="Fill"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Grid>
</UserControl>
This doesn't appear to work in VS2010 designer, but does in VS11. Yet another reason to switch to VS11 beta :)

xaml how to create a trigger isMouseHover on TextBlock

How to create a trigger, which if mouse hover that textblock, the text will change color.
just try this with background or foreground
<TextBlock Text="Hello" Height="20">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="TextBlock.Background" Value="red" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="TextBlockMouseOverStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBlock Background="Blue" Style="{StaticResource TextBlockMouseOverStyle}" Text="Foo" />
</Grid>
</Window>

How can I bind another DependencyProperty to the IsChecked Property of a CheckBox?

Here's an example of what I'm trying to accomplish:
<Window x:Class="CheckBoxBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<CheckBox Name="myCheckBox">this</CheckBox>
<Grid>
<Grid.Resources>
<Style TargetType="ListBox">
<Style.Triggers>
<Trigger Property="{Binding ElementName=myCheckBox, Path=IsChecked}" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ListBox>
<ListBoxItem>item</ListBoxItem>
<ListBoxItem>another</ListBoxItem>
</ListBox>
</Grid>
</StackPanel>
</Window>
When I try to run it, I get this XamlParseException:
A 'Binding' cannot be set on the 'Property' property of type 'Trigger'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
So how can I bind a property on the ListBox to the IsChecked property of a CheckBox?
Try using a DataTrigger. Replace your Grid.Resources with the following and it works:
<Grid.Resources>
<Style TargetType="ListBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myCheckBox, Path=IsChecked}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>

Resources