I have created a custom control as you see below (Generic.xaml):
<Style TargetType="{x:Type local:MyCC}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCC}">
<Grid Name="grd" Height="{Binding Height}" Width="{Binding Width}">
<Rectangle Name="FirstRec" Fill="Blue"/>
<Rectangle Name="SecondRec" Fill="Black" Margin="1"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property = "IsMouseOver" Value = "True">
<Setter Property = "Background" Value = "Red" />
</Trigger>
</Style.Triggers>
</Style>
For FirstRec I want to get the Foreground color of the CC (instead of blue) and for the SecondRec I need to get the Background (instead of black). Therefore now the trigger does not work properly! I also don't want to bind the Height and Width of the Grid because the CC has its own height and width but I don't know how to use it! Would you please help me?!
EDIT:
It is actually a switch that has a status. if status == 0 it shows an empty rectangle. if status == 1 it shows a filled rectangle. if status == 3 || status == 4 it shows a red cross on it. here is the cc:
<Style TargetType="{x:Type local:BreakerCC}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BreakerCC}">
<Grid Name="grd" Background="{TemplateBinding Background}" >
<Rectangle Name="MainRectangle" StrokeThickness="1" Stroke="{TemplateBinding Foreground}"/>
<Path Name="Line1" Stroke="Red" StrokeThickness="1" Stretch="Fill">
<Path.Data>
<LineGeometry StartPoint="0,0" EndPoint="1,1" />
</Path.Data>
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="0x00">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x01">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x02">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x03">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
<Path Name="Line2" Stroke="Red" StrokeThickness="1" Stretch="Fill">
<Path.Data>
<LineGeometry StartPoint="0,1" EndPoint="1,0" />
</Path.Data>
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="0x00">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x01">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x02">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="0x03">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And this is the definition in MainWindow.xaml
<Window.Resources>
<Style x:Key="230KV" TargetType="Control">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="132KV" TargetType="Control">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="Green"/>
</Style>
<Style x:Key="400KV" TargetType="Control">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="Purple"/>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<CC:BreakerCC Status="{Binding Status}" Style="{StaticResource 132KV}" Height="20" Width="20"/>
</StackPanel>
</Grid>
But when the status is 3 or 4 i need to change the Foreground to Red and that doesn't work!
Use TemplateBindings for the Brushes. Binding Width and Height is not at all necessary.
<Style TargetType="local:MyCC">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyCC">
<Grid>
<Rectangle Fill="{TemplateBinding Foreground}"/>
<Rectangle Fill="{TemplateBinding Background}" Margin="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
As a note, instead of a Grid you would usually have a Border element and assign TemplateBindings to its Background, BorderBrush and BorderThickness properties - as done by default by Visual Studio when you create a new custom control.
EDIT: It seems that you do not need a custom control at all. Just create ContentControl styles like these:
<Window.Resources>
<Style TargetType="ContentControl" x:Key="BaseStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Path x:Name="path" Stroke="{TemplateBinding Foreground}"
Data="{TemplateBinding Content}" Stretch="Fill"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="0">
<Setter TargetName="path"
Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="1">
<Setter TargetName="path"
Property="Visibility" Value="Hidden"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Black"/>
<Setter Property="BorderBrush" Value="{Binding Foreground,
RelativeSource={RelativeSource Self}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
</Style>
<Style x:Key="230KV" TargetType="ContentControl" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="132KV" TargetType="ContentControl" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Green"/>
</Style>
<Style x:Key="400KV" TargetType="ContentControl" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Purple"/>
</Style>
</Window.Resources>
<StackPanel>
<ContentControl Style="{StaticResource 230KV}">
<PathGeometry>M0,0 L1,1 M0,1 L1,0</PathGeometry>
</ContentControl>
<ContentControl Style="{StaticResource 132KV}">
<PathGeometry>M0,0 L1,1 M0,1 L1,0</PathGeometry>
</ContentControl>
<ContentControl Style="{StaticResource 400KV}">
<PathGeometry>M0,0 L1,1 M0,1 L1,0</PathGeometry>
</ContentControl>
</StackPanel>
Related
I'm trying to create a round button which has a border shown when hovering and has an object binded color.
I tried to make this but when thes button's color is other than transparent, I can't click on it. Could you help me pls ? I am new to wpf and don't understand everything about it.
<Page.Resources>
<DataTemplate x:Key="Stone">
<StackPanel DataContext="{Binding}">
<Border CornerRadius="15" Height="30" Width="30" Margin="0" >
<Button Content="{Binding}" Tag="{Binding Name}" Height="30" Width="30" Margin="0" Click="Button_Click" Background="Transparent" BorderThickness="0">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding StrColor}" Value="black">
<Setter Property="Background" Value="Black"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding StrColor}" Value="white">
<Setter Property="Background" Value="White"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding StrColor}" Value="none">
<Setter Property="Background" Value="Transparent"></Setter>
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="BorderThickness" Value="3"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Goban">
<ItemsControl ItemsSource="{Binding }" ItemTemplate="{DynamicResource Stone}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
</Page.Resources>
<StackPanel Name="Goban">
<ItemsControl Height="570" Margin="20" x:Name="LstPlateau" ItemsSource="{Binding LstPlateau, Mode=Default}" ItemTemplate="{DynamicResource Goban}">
<ItemsControl.Background>
<ImageBrush ImageSource="../Pictures/goban19.png" Stretch="Fill" />
</ItemsControl.Background>
</ItemsControl>
</StackPanel>
For more details, i'm using mvvm light and, when I click a transparent button, the command fire but it don't whith other color (breakpoint not reached in the command).
Thank you for your help :)
The button is inside the border and "invisible"
To get a round button (or another shape other than rectangular), you need to change the template of the button itself.
Here's an example of a FULL circular button template.
Record it in a resource dictionary and use it in your button.
I did not set color bindings, because I did not understand from your code where they are used.
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ButtonRoundStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{DynamicResource FocusVisual}"/>
<Setter Property="Background" Value="{DynamicResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{DynamicResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse x:Name="ellipse"
Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{Binding BorderThickness.Left, RelativeSource={RelativeSource AncestorType=Button}}"
Fill="{TemplateBinding Background}" SnapsToDevicePixels="true">
</Ellipse>
<ContentPresenter x:Name="contentPresenter" Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="true">
<Setter Property="Stroke" TargetName="ellipse" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="ellipse" Value="{DynamicResource Button.MouseOver.Background}"/>
<Setter Property="Stroke" TargetName="ellipse" Value="{DynamicResource Button.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Fill" TargetName="ellipse" Value="{DynamicResource Button.Pressed.Background}"/>
<Setter Property="Stroke" TargetName="ellipse" Value="{DynamicResource Button.Pressed.Border}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="ellipse" Value="{DynamicResource Button.Disabled.Background}"/>
<Setter Property="Stroke" TargetName="ellipse" Value="{DynamicResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{DynamicResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
All keys are obtained through DynamicResource.
Therefore, they can be redefined at the place where the template is applied.
I edited the question, in my project I try ...
After complementing the question with the complete XAML code, if I understood it correctly, the pattern I showed is applied like this:
<Button Content="{Binding}" Tag="{Binding Name}"
Height="130" Width="130" Margin="0"
Click="Button_Click">
<Button.Resources>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="Gray"/>
</Button.Resources>
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource ButtonRoundStyle}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding StrColor}" Value="black">
<Setter Property="Background" Value="Black"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding StrColor}" Value="white">
<Setter Property="Background" Value="White"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding StrColor}" Value="none">
<Setter Property="Background" Value="Transparent"></Setter>
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderThickness" Value="3"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I am have made the following usercontrol, and all works well except the 2 Background setter properties with value transparent for both isMouseOver and IsSelected that do nothing..
<UserControl.Resources>
<DataTemplate x:Key="DeviceItemTemplate">
<Border Padding="10,5" Margin="10" BorderThickness="4" BorderBrush="Green" CornerRadius="20" Height="150" Width="150">
<StackPanel Orientation="Vertical">
<TextBox Name="screenNameTextBox"
Margin="10" Height="20"
Text="{Binding Name}" />
<TextBox
Margin="10" Height="20"
Text="{Binding Location}" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate x:Key="DeviceItemTemplateSelected">
<Border Padding="10,5" Margin="10" BorderThickness="4" BorderBrush="Orange" CornerRadius="20" Height="150" Width="150" >
<StackPanel Orientation="Vertical" >
<TextBox Name="screenNameTextBox"
Margin="10" Height="20"
Text="{Binding Name}" />
<TextBox
Margin="10" Height="20"
Text="{Binding Location}" />
</StackPanel>
</Border>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="DeviceContainerStyle">
<Setter Property="ContentTemplate" Value="{DynamicResource DeviceItemTemplate}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{DynamicResource DeviceItemTemplateSelected}"/>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Border
Grid.Column="0"
Margin="10"
BorderBrush="Silver"
BorderThickness="1">
<ListBox ItemsSource="{Binding Devices, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedScreen, Mode=TwoWay}"
ItemContainerStyle="{StaticResource DeviceContainerStyle}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Border>
This is how it looks
I also tried white, but got same results. I cannot get rid of this blue background.
What am I overlooking please?
-----After receiving mm8 answer-----
Placed all his code in a resource dictionary, made some changes to the solidcolorbrush and BorderThickness, and modified the style section from previous to:
<Style BasedOn="{StaticResource ListBoxItemSSDS}" TargetType="{x:Type ListBoxItem}" x:Key="DeviceContainerStyle">
<Setter Property="ContentTemplate" Value="{DynamicResource DeviceItemTemplate}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{DynamicResource DeviceItemTemplateSelected}"/>
</Trigger>
</Style.Triggers>
</Style>
You need to define a custom ControlTemplate for the ListBoxItem to be able to the background of it when the IsMouseOver and IsSelected properties are set.
You can right-click on a ListBoxItem in design mode in Visual Studio or in Blend and choose Edit Template->Edit a Copy to copy the default template into your XAML markup and then edit it as per your requirements.
Here is what it looks like and the resources that are involved:
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/>
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You may for example change the Color of the Item.MouseOver.Background and Item.SelectedActive.Background resources.
I created a WPF TextBox with Placeholder text by creating a customized Style that overlays one TextBox (as a placholder text) on another TextBox in the ControlTemplate.
Here's the Style definition:
<Style x:Key="TextBoxFormBaseStyle"
BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox x:Name="_textSource"
Panel.ZIndex="2"
Background="Transparent"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="_textTag"
Panel.ZIndex="1"
Focusable="False"
Text="{TemplateBinding Tag}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference _textSource}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, Source={x:Reference _textSource}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
<!-- Move Focus to child control -->
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="_textSource" Property="FocusManager.FocusedElement" Value="{Binding ElementName=_textSource}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A Trigger on Property IsFocused allows focusing the the child TextBox control (named _textSource) when navigating through multiple TextBox's by Tab key.
Navigating to the previous element by pressing SHIFT + Tab is not working. How can I get SHIFT + Tab to set the focus to the previous element?
There are better ways to add a watermark if you want the TextBox to actuallty behave and get focused like a built-in TextBox. Try this style:
<Style x:Key="TextBoxFormBaseStyle" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<TextBox x:Name="_textTag"
Focusable="False"
Text="{TemplateBinding Tag}"
BorderThickness="0">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, RelativeSource={RelativeSource AncestorType=TextBox}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample usage:
<TextBox OpacityMask="Red" Tag="Red Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />
<TextBox OpacityMask="Green" Tag="Green Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />
I wanted to add a style to a DataGridCell in my app to have the effect of a watermarked "hint" in case the cell is empty to give the user a hint about what he needs to type in the cell.
<Window.Resources>
<Style x:Key="WatermarkTextBox" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid>
<Border x:Name="BorderBase" Background="White" BorderThickness="1.4,1.4,1,1" BorderBrush="Red">
<Label x:Name="TextPrompt"
Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag}"
Background="{TemplateBinding Background}" Visibility="Visible"
Focusable="False" Foreground="Silver"/>
</Border>
<!--<ScrollViewer Margin="0" x:Name="PART_ContentHost" Foreground="Black"/>-->
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False"/>
<Condition Property="Content" Value=""/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="TextPrompt" Value="Visible"/>
</MultiTrigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" TargetName="BorderBase" Value="Black"/>
<Setter Property="Visibility" TargetName="TextPrompt" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="DimGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And this is my code:
Style style = this.FindResource("WatermarkTextBox") as Style;
myCell.Tag = "input position here please";
myCell.Style = style;
And it works fine. When this code is executed, the watermark style is applied correctly. But when I focus on the cell, I cannot write anything.
I mean, the "IsFocused" trigger is executed and the Label is collapsed (it disappears) but I cannot input anything inside the cell.
You are missing a ContentPresenter:
<Style x:Key="WatermarkTextBox" TargetType="{x:Type DataGridCell}">
<Setter Property="Tag" Value="insert" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid>
<Border x:Name="BorderBase" Background="White" BorderThickness="1.4,1.4,1,1" BorderBrush="Red">
<Label x:Name="TextPrompt"
Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag}"
Background="{TemplateBinding Background}" Visibility="Visible"
Focusable="False" Foreground="Silver"/>
</Border>
<ContentPresenter x:Name="cp" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False"/>
<Condition Property="Content" Value=""/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="TextPrompt" Value="Visible"/>
<Setter Property="Visibility" TargetName="cp" Value="Collapsed"/>
</MultiTrigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" TargetName="BorderBase" Value="Black"/>
<Setter Property="Visibility" TargetName="TextPrompt" Value="Collapsed"/>
<Setter Property="Visibility" TargetName="cp" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="DimGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try This, Updated
<Style x:Key="WatermarkTextBox" TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Grid>
<Border
x:Name="border"
SnapsToDevicePixels="True">
<ScrollViewer
x:Name="PART_ContentHost"
Focusable="False"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" />
</Border>
<TextBlock
x:Name="placeholder"
VerticalAlignment="Center"
IsHitTestVisible="False"
Text="{TemplateBinding Tag}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}" Value="">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="border" Property="Opacity" Value="0.56" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#FF7EB4EA" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#FF569DE5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Usage
<DataGrid.Columns>
<DataGridTemplateColumn Header=" Tags ">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Style="{StaticResource WatermarkTextBox}"
FontSize="12"
VerticalAlignment="Center"
Tag="Stage Name .."
Width="60"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I want to Style an Border inside a ControlTemplate. But I don't know how to access it. My Style looks like this:
<Style x:Key="RedCell" TargetType="DataGridCell" BasedOn="{StaticResource MYDGCellStyle}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Grid>
<Grid Grid.ZIndex="86" x:Name="CellContenGrind" Background="{TemplateBinding Background}" />
<Border Grid.ZIndex="87" x:Name="ContentBorder" BorderBrush="White" Background="Crimson" CornerRadius="25">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Grid Grid.ZIndex="88" x:Name="CellGridFocused"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" TargetName="CellGridFocused" Value="{DynamicResource Brush_DataGridCellFocused}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="CellContenGrind" Value="{DynamicResource Brush_DataGridSelected}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ungelesen}" Value="0">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
I need the Background="{TemplateBinding Background}" on my CellContentGrind because of some other stuff, so I can't just move that to my Border.
If ungelesen = 0, I want the Background of my ContentBorder to be Green. How can I do that?
Why not move the Style to the Border itself?
<Border Grid.ZIndex="87"x:Name="ContentBorder" BorderBrush="White" CornerRadius="25">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Crimson" />
<Style.Triggers>
<DataTrigger Binding="{Binding ungelesen}" Value="0">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
Note that Background is set with Setter now to make overridable with DataTrigger.