Common Style for PasswordBox and TextBox - wpf

How can I define a common Style for the TextBox and the PasswordBox?
My approach, I have define a Style for the TargetType FrameworkElement but this doesnt work as common style, then few propertys doesnt exist on the FrameworkElement.
My TextBox Style is equals the PasswordBoxStyle
<Style TargetType="{x:Type TextBox}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="MinHeight" Value="30"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Name="Border" CornerRadius="4" Padding="2" Background="White" BorderBrush="Black" BorderThickness="1" >
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Try something like this
<Style x:Key="textboxPasswordboxStyles">
<Setter Property="Control.ControlProperty" Value="value" />
<Setter Property="TextBox.TextboxSpecproperty" Value="value" />
<Setter Property="PasswordBox.PasswordBoxSpecProperty" Value="value" />
</Style>
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource textboxPasswordboxStyles}">
</Style>
<Style TargetType="{x:Type PasswordBox}"
BasedOn="{StaticResource textboxPasswordboxStyles}">
</Style>

<Style x:Key="textboxPasswordboxStyles" TargetType="Control">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="Height" Value="20" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="MaxHeight" Value="22"/>
<Setter Property="BorderThickness" Value="1.5"/>
<Setter Property="AllowDrop" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<Grid>
<Border Name="Border" CornerRadius="8" BorderThickness="{TemplateBinding BorderThickness}" >
<Border.Background>
<SolidColorBrush Color="White" x:Name="Background" />
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="Gray" x:Name="BorderBrush" Opacity="1"/>
</Border.BorderBrush>
<ScrollViewer Margin="10,0,10,0" x:Name="PART_ContentHost" VerticalAlignment="Center"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TextBox"
BasedOn="{StaticResource textboxPasswordboxStyles}">
</Style>
<Style TargetType="PasswordBox"
BasedOn="{StaticResource textboxPasswordboxStyles}">
</Style>

Related

WPF Style design TextBox Tooltip

I would like to style the Tooltip of Textboxes which are used for validation. I'm trying to get a rounded corners Tooltip without sucess. How may I get it from ResourceDictonary?
With the code below, I'm getting the Tooltip text on validation error with a rectangular border. Here is my code:
<ResourceDictionary>
<!-- Textbox with validation capabilities -->
<Style x:Key="ValidableTextBox" TargetType="TextBox">
<Style.Resources>
<Style x:Key="ToolTip" TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Name="Border" CornerRadius="4" BorderThickness="1" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Height" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
I just realized that BorderBrush property was missing, thanks to Muhammad for he made it working (remove the x:Key="ToolTip"), here is the updated code:
<ResourceDictionary>
<!-- Textbox with validation capabilities -->
<Style x:Key="ValidableTextBox" TargetType="TextBox">
<Style.Resources>
<Style TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Name="Border" CornerRadius="4" BorderThickness="1" BorderBrush="Red" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Height" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>

TextBox ControlTemplate inside of a Style with InputBindings

I've created a WPF Style for a TextBox with an InputBindings (KeyBinding for Enter) inside the ControlTemplate.
Style and InputBindings is working fine for my TextBoxes, but if I use this Style for my TextBoxes the TabOrder/TabStop is not working any more.
This is the style:
<Style x:Key="TextBoxTemplate" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="FontSize" Value="16"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="5,0,5,5"/>
<Setter Property="Width" Value="150"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox Text="{TemplateBinding Text}">
<TextBox.InputBindings>
<KeyBinding Command="{Binding EnterKeyCommand}" Key="Enter"/>
</TextBox.InputBindings>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How I add it to my TextBoxes:
<TextBox Text={Binding FirstName} Style="{StaticResource TextBoxTemplate}">
<TextBox Text={Binding LastName} Style="{StaticResource TextBoxTemplate}">
I think the problem is that I use a TextBox inside of the ControlTemplate.
But I don't know how to get running the InputBindings without the TextBox inside of the Template
Do you have any idea?
Thanks Phil
Modify your template to look like the original one plus your KeyBinding:
<Style x:Key="TextBoxTemplate" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="FontSize" Value="16"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="5,0,5,5"/>
<Setter Property="Width" Value="150"/>
<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">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<ScrollViewer.InputBindings>
<KeyBinding Command="{Binding EnterKeyCommand}" Key="Enter"/>
</ScrollViewer.InputBindings>
</ScrollViewer>
</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>

ControlTemplate.Trigger never triggers on Datagrid Cell Focus

<Style x:Key="Body_Content_DataGrid_Centering" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="DarkGray" />
<Setter Property="BorderThickness" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have included above code in App.xaml file. But the trigger function never triggers on DataGrid cell focus. Can anyone explain why this happens?
Try use FocusVisualStyle. With it, you can set the focus frame and additional values.
Sample:
<!-- CellFocusVisual -->
<Style x:Key="CellFocusVisual" TargetType="{x:Type Control}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<Border SnapsToDevicePixels="True" CornerRadius="0" BorderThickness="2" BorderBrush="#7B2F81" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- DataGridCell -->
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="FocusVisualStyle" Value="{StaticResource CellFocusVisual}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border x:Name="BackgroundBorder" BorderThickness="3" Background="Transparent">
<ContentPresenter VerticalAlignment="Center" Margin="4,0,6,0" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Focuses are different. See the link for more information.

WPF DataGridCell, Style.Trigger, basedon multiple styles

I have got this problem with styles in WPF.
I want every cells in row in red color.
When I use two styles for one cell MyCellStyle and RightCellStyle (based on MyCellStyle) the result is:
image
Here is may code for MyCellStyle and RightCellStyle
<Style x:Key="MyCellStyle" TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedRowColor}" />
<Setter Property="BorderBrush" Value="#FFDFE9F5" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</Style.Triggers>
<Style x:Key="RightCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource MyCellStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Right" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
And here is part where I set red Color
<DataGrid.Style>
<Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="DataGridCell" BasedOn="{StaticResource MyCellStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsNew}" Value="True">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>

Validation.ErrorTemplate Style Issue

I am trying to apply a style to a text box when the content is not valid.
The following style works:
<Style x:Key="textBoxNormalStyle" TargetType="{x:Type TextBox}">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="ForceCursor" Value="False"/>
<Setter Property="Foreground" Value="{StaticResource TextColor}"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="3,0,3,0"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{StaticResource TextBackColor}" BorderBrush="{StaticResource BorderColor}" x:Name="Bd" CornerRadius="4" BorderThickness="2">
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="ForceCursor" Value="False"/>
<Setter Property="Foreground" Value="{StaticResource TextColor}"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="3,0,3,0"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid Name="test">
<Border Background="{StaticResource TextBackColor}" BorderBrush="#d99" x:Name="Bd" CornerRadius="4" BorderThickness="2">
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
<Image Name="ErrorImage" Width="24" Height="24" Margin="0,0,4,0" Source="/Images/error.png" HorizontalAlignment="Right">
</Image>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
However I want to get rid of the trigger above and move the control template within the trigger to the Validation.ErrorTemplate section. But when I do this the control for the error template does not display correctly (the size of the error template defaults to the size of the image contained within it, left aligned, and blocks the text the user might have typed in the textbox).
Is there a cleaner way for the xaml above?
The ErrorTemplate is an adorner, not a replacement for the control template. You include an AdornedElementPlaceholder in the template where you want to leave space for the original control. So, your error template should look like:
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid Name="test">
<AdornedElementPlaceholder/>
<Image Name="ErrorImage" Width="24" Height="24" Margin="0,0,4,0" Source="/Images/error.png" HorizontalAlignment="Right"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Since you also want to change the color of the border, I would use a TemplateBinding for the border brush and change that in the Validation.HasError trigger:
<Setter Property="BorderBrush" Value="{StaticResource BorderColor}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{StaticResource TextBackColor}" BorderBrush="{TemplateBinding BorderBrush}" x:Name="Bd" CornerRadius="4" BorderThickness="2">
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="#d99"/>
</Trigger>
</Style.Triggers>

Resources