I borrowed some code from some other guy here on Stack Overflow. I have two PasswordBoxes. I want the first one to show "Password" and the second one to show "Re-enter Password". I don't want to rewrite the complete style all over again if the only difference is the text in the TextBlock. How can I override and change the value of the TextBlock, if the TargetType has to be PasswordBox? I'm trying to create a second style that is based on the first one, and then change it from there, but I'm not sure about the syntax.
This one works fine:
<Style x:Name="customPWBStyle" x:Key="customPasswordBox"
TargetType="{x:Type PasswordBox}">
<Setter Property="helper:PasswordBoxMonitor.IsMonitoring"
Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="true">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<TextBlock Text="Password"
Margin="4, 2, 0, 0"
Foreground="Gray"
Visibility="Collapsed"
Name="txtPrompt" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Bd"
Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="helper:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But I want to create another style identical, but the only difference has to be the TextBlock that has to say "Re-enter password"
This is what I got so far:
<Style x:Key="reEnterPasswordBox" BasedOn="{StaticResource customPasswordBox}" TargetType="{x:Type PasswordBox}">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="Re-enter Password"></Setter>
</Style>
</Style.Resources>
</Style>
However it does not work. I can see that theres a name for the TextBlock, which is txtPrompt, but I'm not sure if its possible to use that as a reference for chaning the value of the TextBlock.
I would recommend to create a special dependency property in customPasswordBox, e.g. InputHint. (If you can't change customPasswordBox code, make a custom attached dependency property - like helper:PasswordBoxMonitor.IsMonitoring. Attached DPs are great for parametrizing templates)
When you have a property, set default value via Setter, and then bind TextBlock to it via TemplateBinding.
<Style x:Name="customPWBStyle" x:Key="customPasswordBox"
TargetType="{x:Type PasswordBox}">
<Setter Property="helper:PasswordBoxMonitor.IsMonitoring" Value="True"/>
<Setter Property="InputHint" Value="Password"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="true">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<TextBlock Text="{TemplateBinding InputHint}"
Margin="4, 2, 0, 0"
Foreground="Gray"
Visibility="Collapsed"
Name="txtPrompt" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Bd"
Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="helper:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
to make another style, change only Setter for InputHint:
<Style x:Key="reEnterPasswordBox" BasedOn="{StaticResource customPasswordBox}" TargetType="{x:Type PasswordBox}">
<Setter Property="InputHint" Value="Re-enter Password"/>
</Style>
Parts of template are not easily reachable for modification, even with implicit styles
Related
for some reason in my code behind (WPF), the "setter" section makes the text box not function anymore. I can't type in it or add any functionality to it. When I remove the setter section, the text box works. I've seen other people online do it this exact way and it works for them but I'm not sure what I'm doing wrong.
Here's what I have in the main window.
<TextBox Style="{DynamicResource inputBox}" Margin="0,50,125,0"/>
And here's what I have in the code behind
<Style x:Key="inputBox" TargetType="TextBox">
<Setter Property="Padding" Value="3"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="65"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Text" Value=""/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<!--This setter somehow breaks the text box-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="Transparent" CornerRadius="5" BorderThickness="1" BorderBrush="Black">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks
Your template only shows the border. Not the content. It needs a PART_ContentHost Do yourself a favor and copy the existing template and edit that. You can do this on the XAML designer. For example, here is what it looks like when I copy it on mine:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</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="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
I have a Button that I want to have an Orange Background with a White Foreground. When I mouse over the Button I would like it to display in DarkOrange. This is the Style I am using at the moment.
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="DarkOrange"/>
</Trigger>
</Style.Triggers>
</Style>
If I don't modify the original Background color of the my Button this style works fine. For example;
<Button Grid.Row="2" Content="SIGN IN" />
has no issues. However, when I want to change the default Background of the Button, i.e
<Button Grid.Row="2" Content="SIGN IN" Background="Orange"/>
the style does not work. I assume this is because I am now overriding the Background property that the IsMouseOver is attempting to change.
Is there a way I can achieve both a modified default Background and a IsMouseOver effect? I have also tried setting <Border Background="Orange"> but to no effect still.
You could just add a setter to your Style instead of adding a Background property to your Button. Like this:
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Orange"/>
<Setter Property="Template">
...
</Setter>
<Style.Triggers>
...
</Style.Triggers>
</Style>
Here is an another example of how to use it.
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate x:Name="Border" TargetType="{x:Type Button}">
<Border x:Name="Border" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="CP" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="CP" Property="TextBlock.Foreground" Value="White"/>
<Setter TargetName="Border" Property="Background" Value="DarkOrange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This working fine with
<Button Grid.Row="2" Content="SIGN IN" Background="Orange"/>
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.
I'm trying to style a button in XAML. Below you can see what I created so far.
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#f2f2f7"/>
<Setter Property="Padding" Value="6,4"/>
<Setter Property="Foreground" Value="#222222" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="1" Background="{TemplateBinding Background}" BorderThickness="1" BorderBrush="#b1b1c0">
<Border CornerRadius="1" Background="{TemplateBinding Background}" BorderThickness="1,1,1,0" BorderBrush="#f8f8fa" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
</ContentPresenter>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#8e8eba" />
<Setter Property="Foreground" Value="#f2f291" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem is, that this button has two <Border> elements nested one in another. I'd like to have different BorderBrush="" attribute when IsMouseOver trigger is activated. For example, when I put mouse over button, the inner border would red, and outer border would be blue.
Can you help me with that?
Try set the Name for Borders and use TargetName in Trigger like this:
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#f2f2f7"/>
<Setter Property="Padding" Value="6,4"/>
<Setter Property="Foreground" Value="#222222" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="OuterBorder" CornerRadius="1" Background="{TemplateBinding Background}" BorderThickness="1" BorderBrush="#b1b1c0">
<Border Name="InnerBorder" CornerRadius="1" Background="{TemplateBinding Background}" BorderThickness="1,1,1,0" BorderBrush="#f8f8fa" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#8e8eba" />
<Setter Property="Foreground" Value="#f2f291" />
<!-- Here use TargetName -->
<Setter TargetName="OuterBorder" Property="BorderBrush" Value="Red" />
<Setter TargetName="InnerBorder" Property="BorderBrush" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Some notes
TargetName can be set in only <ControlTemplate.Triggers>, not in <Style.Triggers>
TargetName operates only within the one ControlTemplate section
Give the Border a name and use the TargetName property on the trigger setter.
<Setter TargetName="MyBorderName" Property="BorderBrush" Value="Red" />
I'm trying to change the borderbrush property of a button in a custom template. Changing the background on mouseover using this method works just fine, but the BorderBrush? Nada.
Here's my code:
<Style x:Key="ImageButtonStyle" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Margin="1,0,0,-9">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,1,1,0" Height="94" Width="101"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit: Actually not even the blue borderbrush set at the beggining shows up so that may be of relevance.
Here's where the style is used if of any importance.
<Button Margin="191,10,138,109" Style="{StaticResource ImageButtonStyle}">
<Image/>
</Button>
You create style setting BorderThickness to 3 but then override default visual tree so this thicknes is not taken into acount. Add this
BorderThickness="{TemplateBinding BorderThickness}"
in order to see it.