I have a style for my path object this path is surrounded by a border when I'm writing a trigger that is not working until I went on to actual path object.
Style
<Style TargetType="Path">
<Setter Property="Stroke" Value="{DynamicResource CloseButtonClr}"></Setter>
<Setter Property="Stretch" Value="Uniform"></Setter>
<Setter Property="StrokeThickness" Value="3"></Setter>
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="True">
<Setter Property="Stroke" Value="{DynamicResource LableClr}"/>
</Trigger>
</Style.Triggers>
</Style>
<Border Width="20" Grid.Column="2" Background="Transparent" Margin="0,0,5,0" >
<Path Data="M0,0 L1,1 M0,1 L1,0" />
</Border>
this is my code if I went on the path object then the trigger is working if went in between border and path object the trigger is not working, please help me wt I'm missing thanks
Use a DataTrigger to bind to the IsMouseOver property of the Border:
<Style TargetType="Path">
<Setter Property="Stroke" Value="{DynamicResource CloseButtonClr}"></Setter>
<Setter Property="Stretch" Value="Uniform"></Setter>
<Setter Property="StrokeThickness" Value="3"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" Value="{DynamicResource LableClr}"/>
</Trigger>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=Border}}" Value="True">
<Setter Property="Stroke" Value="{DynamicResource LableClr}"/>
</DataTrigger>
</Style.Triggers>
</Style>
A Trigger in a Path style can only bind to a property of the Path itself. The path Border.IsMouseOver will not bind to the parent Border element. It will bind to the IsMouseOver property of the Path. Both Border and Path inherit from UIElement where the property is actually defined.
Related
I have some TabItems, each one containg one image and a textblock. Here is the code:
<TabItem.Header>
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<StackPanel x:Name="sp" Orientation="Horizontal">
<Image x:Name="img" Source="img0.png"/>
<TextBlock x:Name="tb" Text="Tab1" VerticalAlignment="Center" Foreground="Green"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="TabItem.IsSelected" Value="True">
<Setter TargetName="img" Property="Source" Value="img1.png" />
<Setter TargetName="tb" Property="Foreground" Value="Red" />
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
<Trigger SourceName="sp" Property="IsMouseOver" Value="True">
<Setter TargetName="img" Property="Source" Value="img1.png" />
<Setter TargetName="tb" Property="Foreground" Value="Red" />
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
What I'm trying to achieve is to change the image's source and textblock's foreground value when the TabItem is selected. The IsMouseOver behaviour is working properly but the TabItem.IsSelected is not working as expected.
Basically this code is not doing what I'm thinking it should do:
<Trigger Property="TabItem.IsSelected" Value="True">
<Setter TargetName="img" Property="Source" Value="img1.png" />
<Setter TargetName="tb" Property="Foreground" Value="Red" />
<Setter Property="FontWeight" Value="Bold"/>
Please share your opinion.
Thank you.
You are trying to reach the IsSelected property of the TabItem from the TabItem.Header and that can't be accomplished with an ordinary Trigger. Instead, you need to use a DataTrigger so that you can Bind to the IsSelected property with a RelativeSource Binding:
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=
{x:Type TabItem}}}" Value="True">
<Setter TargetName="img" Property="Source"
Value="/WpfApplication1;component/Images/Tulips.jpg" />
<Setter TargetName="tb" Property="Foreground" Value="Red" />
<Setter Property="TextElement.FontWeight" Value="Bold"/>
</DataTrigger>
In my current project, I have this XAML file where I define the visual style that must be applied to different types of custom widgets.
For example, the style for a 'DirectLineButton' (a custom class that inherits from WPF's Button) is as follows:
<Style x:Key="DirectLineButtonTemplate" TargetType="{x:Type View:DirectLineButton}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="MyBorder"
CornerRadius="2"
BorderThickness="2"
Background="Gold"
BorderBrush="Gray">
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineAvailable">
<Setter TargetName="MyBorder" Property="Background" Value="Gold"/>
</Trigger>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineIdle">
<Setter TargetName="MyBorder" Property="Background" Value="Silver"/>
</Trigger>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineBusy">
<Setter TargetName="MyBorder" Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineCalled">
<Setter TargetName="MyBorder" Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now, I need to replicate this idea by defining the style for a Rectangle. Unfortunately, WPF flags an error message when I try to define a ControlTemplate for a rectangle, can you suggest a workaround for this? See the code below of what I'm trying to attempt:
<Style x:Key="MyRectangleTemplate" TargetType="{x:Type Rectangle}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Rectangle}">
<Border x:Name="MyBorder"
CornerRadius="2"
BorderThickness="2"
Background="Gold"
BorderBrush="Gray">
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineAvailable">
<Setter TargetName="MyBorder" Property="Background" Value="Gold"/>
</Trigger>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineIdle">
<Setter TargetName="MyBorder" Property="Background" Value="Silver"/>
</Trigger>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineBusy">
<Setter TargetName="MyBorder" Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="View:DirectLineButton.State" Value="DirectLineCalled">
<Setter TargetName="MyBorder" Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks in advance!
Hi you will have to do it with Border only.Controls that inherits FrameworkElement only can have Template . But Rectangle , Line etc are lighter versions they inherits only UIElement not FrameworkElement.I hope this will help. Conclusion: Rectange do not have Template property
You can't define a control template for a Rectangle, since it's not a control, but a Shape. You can only define a control template for classes derived from Control.
You should
1) use a Style (not a ControlTemplate) to have rounded borders.
2) Use a Trigger inside your style.
The following Xaml should get you closer from your goal :
<Style x:Key="MyRectangleStyle" TargetType="{x:Type Rectangle}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Fill" Value="Blue"/>
<Setter Property="RadiusX" Value="2" />
<Setter Property="RadiusY" Value="2" />
<Style.Triggers>
<DataTrigger Binding="{Binding DirectLineState}"
Value="{x:Static l:DLS.Available}">
<Setter Property="Fill" Value="Gold"/>
</DataTrigger>
<DataTrigger Binding="{Binding DirectLineState}"
Value="{x:Static l:DLS.Idle}" >
<Setter Property="Fill" Value="Silver"/>
</DataTrigger >
<DataTrigger Binding="{Binding DirectLineState}"
Value="{x:Static l:DLS.Available}">
<Setter Property="Fill" Value="Green"/>
</DataTrigger >
<DataTrigger Binding="{Binding DirectLineState}"
Value="{x:Static l:DLS.Called}">
<Setter Property="Fill" Value="LightBlue"/>
</DataTrigger >
</Style.Triggers>
</Style>
(notice that :
1) i changed the key for "MyRectangleStyle".
2) If you want this Style to be the default Style, do not give it a Key, but just a TargetType...
3) ...OR set the Key to "{x:Type Rectangle}". msdn seems to prefer that way.
btw : shouldn't you be using DataTriggers on public properties instead of Triggers ? but i don't know the whole architecture of your application. )
Rq : for the code above to work, you need :
1) a public proprety called DirectLineState raising NotifyPropertyChanged on change.
2) an enum called DLS defined in a separate file (like a class) in your project
3) you need "l" to be your project NameSpace.
<xmlns:l="clr-namespace:MyProjectNameSpace" >
4) Assign Style and set proper DataContext for the Rectangle
I created a style for a hyperlink control:
<Style x:Key="MyHyperlink" TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource HyperlinkBrush}" />
<Setter Property="IsEnabled" Value="{Binding IsEnabled,RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}}" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Foreground" Value="{StaticResource HyperlinkMouseOverBrush}" />
</Trigger>
</Style.Triggers>
</Style>
How can I use this style in a DataGridHyperlinkColumn?
The ElementStyle of this kind of column asks for a TextBlock style instead of an Hyperlink one...
<DataGridHyperlinkColumn EditingElementStyle="{StaticResource MyDataGridTextColumn}" ElementStyle="{StaticResource MyDataGridHyperlinkColumn}"
Header="WebSite" Binding="{Binding Site, NotifyOnValidationError=True,ValidatesOnDataErrors=True}" />
Remove the x:Key from your style and put it in DataGrid.Resources then it targets all Hyperlink controls within this DataGrid.
I have a WPF Listview, and I have overridden the ListView.ItemTemplate to change the background color of the items on the ListViewItem.IsMouseOver event like so:
<AlternationConverter x:Key="BackgroundConverter">
<SolidColorBrush>White</SolidColorBrush>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color A="242" R="242" G="242" B="242" />
</SolidColorBrush.Color>
</SolidColorBrush>
</AlternationConverter>
<Style x:Key="alternatingWithBinding" TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="31"/>
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource BackgroundConverter}}"/>
<Style.Triggers>
<Trigger Property="ListViewItem.IsSelected" Value="True">
<Setter Property="ListViewItem.Background" Value="Yellow" />
</Trigger>
<Trigger Property="ListBoxItem.IsMouseOver" Value="True">
<Setter Property="ListBoxItem.Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
What I'm trying to achieve is to have a different color when hovered over the already selected item (which is yellow). So on all the items it will be a Blue hover-over, and on the selected Yellow item, it'll be green.
I tried the below attempt, using MultiTrigger, but that didn't do the trick:
<Style x:Key="alternatingWithBinding" TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="31"/>
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource BackgroundConverter}}"/>
<Style.Triggers>
<Trigger Property="ListViewItem.IsSelected" Value="True">
<Setter Property="ListViewItem.Background" Value="Yellow" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ListBoxItem.IsMouseOver" Value="True"/>
<Condition Property="ListBoxItem.IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="ListBoxItem.Background" Value="Green" />
</MultiTrigger>
<Trigger Property="ListBoxItem.IsMouseOver" Value="True">
<Setter Property="ListBoxItem.Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
Any ideas?
Thanks.
Are the triggers are applied in order? It might work if you move the MultiTrigger to the bottom, then it will apply after the IsMouseOver Trigger.
I have an user control, It is editable text block. The content of the control is:
<DataTemplate x:Key="DisplayModeTemplate">
<TextBlock
Text="{Binding ElementName=mainControl, Path=FormattedText}"
Margin="5,3,5,3" />
</DataTemplate>
<Style TargetType="{x:Type Controls:EditableTextBlock}">
<Setter Property="ContentTemplate" Value="{StaticResource EditModeTemplate}"/>
<Style.Triggers>
<Trigger Property="IsInEditMode" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource EditModeTemplate}" />
</Trigger>
<Trigger Property="IsInEditMode" Value="False">
<Setter Property="ContentTemplate" Value="{StaticResource DisplayModeTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
Also i have another window with tree view:
When treeView1_KeyDown fires I set IsInEditMode to true, but it seems that trigger doesn't work, because content template don't change. Anyone, please explain me why?
Have you tried removing the default setter?
i.e. change your style code to:
<Style TargetType="{x:Type Controls:EditableTextBlock}">
<Style.Triggers>
<Trigger Property="IsInEditMode" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource EditModeTemplate}" />
</Trigger>
<Trigger Property="IsInEditMode" Value="False">
<Setter Property="ContentTemplate" Value="{StaticResource DisplayModeTemplate}" />
</Trigger>
</Style.Triggers>
</Style>