Adding parameters to style - wpf

I am trying to create a simple button:
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="0" BorderThickness="1" BorderBrush="#83a5d2" x:Name="border">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#e8f1fe" Offset="0"/>
<GradientStop Color="#cbe1fe" Offset="0.5"/>
<GradientStop Color="#a3c7f1" Offset="0.50"/>
<GradientStop Color="#cceffe" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter VerticalAlignment="Center" x:Name="contentPresenter"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But how can I change the CornerRadius? I want to be able to pass a property to the object so that the object will have that corner radius. I cannot use templatebinding because Button does not have a property called CornerRadius.

You can directly use the "Border.CornerRadius" property in your styles. For the sake of simplicity I skipped most other attributes:
<Style x:Name="myBtnStyle" TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Border.CornerRadius" Value="3" />
<!-- more... -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="bdContent" CornerRadius="{TemplateBinding Border.CornerRadius}">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

To bind the corner radius to a value you want to set programatically, you could declare it in your Xaml...
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="{Binding MyCornerRadius}" BorderThickness="1" BorderBrush="#83a5d2" x:Name="border">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#e8f1fe" Offset="0"/>
<GradientStop Color="#cbe1fe" Offset="0.5"/>
<GradientStop Color="#a3c7f1" Offset="0.50"/>
<GradientStop Color="#cceffe" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter VerticalAlignment="Center" x:Name="contentPresenter"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then create the button(s)...
<Button Style="{StaticResource ButtonStyle}" Content="Hello" DockPanel.Dock="Top" />
And then in your code behind, you could set it...
public CornerRadius MyCornerRadius { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyCornerRadius = new CornerRadius(5, 6, 6, 5);
}
And this will give the effect you're after.

Related

IsMouseOver is false when mouse is over child elements in custom WPF button template

I'm trying to create a straight-forward, colored button in WPF that changes colors when the mouse is over and again when the button is pressed. I've been working in web projects lately and it's insane how much more complicated styling WPF is vs. HTML.
Commentary aside, although the MS documentation on UIElement.IsMouseOver states that it includes child elements, I'm experiencing the opposite. My trigger changes the color when my pointer is right over the border of the button, but as soon as it moves a few pixels farther inward, it changes back. Using Snoop, as I move the pointer pixel by pixel toward the center of the button, I can see that IsMouseOver is true for the border, then for the ContentPresenter, then for the inner TextBlock, but they are mutually exclusive. When IsMouseOver is true for a child element, it's false for the parents. I've seen lots of examples using the same approach as mine, but it's not working. I've gone through quite a few edits so maybe I have some erroneous syntax. How do I make the trigger apply when the mouse is anywhere within the button.
Here is my code. I define the brushes as resources of the button, override the default control template replacing the Chrome border with a regular Border, and then replace the brushes in Style Triggers.
<Grid Name="grdResults" Grid.Row="3" Margin="0" Visibility="Visible">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
...
</Grid.RowDefinitions>
<Button Grid.ColumnSpan="2" Grid.RowSpan="2" Content="X" BorderThickness="1" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,3,0" Padding="5,1">
<Button.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Fill="Transparent" Stroke="WhiteSmoke" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="BorderBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF9B9B9B" Offset="0"/>
<GradientStop Color="#FF666666" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="BackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA21E00" Offset="0"/>
<GradientStop Color="#FF550000" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="MouseOverBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFB63200" Offset="0"/>
<GradientStop Color="#FF681800" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="MouseDownBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF666666" Offset="0"/>
<GradientStop Color="#FF9B9B9B" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="MouseDownBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF550000" Offset="0"/>
<GradientStop Color="#FFA21E00" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="ForegroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#FFB9B9B9" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="MouseDownForegroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFB9B9B9" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Button.Resources>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{StaticResource BackgroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/>
<Setter Property="FontWeight" Value="Bold" />
<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}">
<Border x:Name="Border" CornerRadius="4" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
<ContentPresenter Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource MouseOverBackgroundBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource MouseDownBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MouseDownBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource MouseDownForegroundBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<TextBlock Text="Posts Processed:" HorizontalAlignment="Right" Height="16" VerticalAlignment="Top" Margin="13,0,0,0" />
<TextBlock Grid.Column="1" Name="tbPostsProcessed" Margin="3,0,13,0" Text="{Binding PostsProcessed}" HorizontalAlignment="Left"/>
Edit:
I've also just discovered the MouseOver trigger seems to work everywhere to the right of the X (button content). Very strange. IsPressed also seems to only work on the same pixels that MouseOver works on.

DataGrid Header Style in Silverlight 4.0

I want to set header of datagrid like following link.
Style in HeaderColumn in Datagrid
I have used DataGridColumnHeadersPresenter in my code.
See my following code:
<Style x:Key="XYZ" TargetType="sdk:DataGridColumnHeadersPresenter" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridRowGroupHeader">
<Border x:Name="ButtonBorder"
CornerRadius="0,0,0,0"
BorderThickness="0"
BorderBrush="Transparent">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#555" Offset="0.0"/>
<GradientStop Color="#000" Offset="0.8"/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ItemsPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="BreakGridStyle" TargetType="sdk:Datagird">
<Setter Property="HeadersVisibility" Value="Column" />
<Setter Property="AutoGenerateColumns" Value="False" />
<Setter Property="Width" Value="Auto" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGrid">
<Grid>
<StackPanel>
<sdk:DataGridColumnHeadersPresenter Name="ABC" Style="{StaticResource XYZ}" />
<ItemsPresenter/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But i got following Error:
The property 'Template' was not found in type 'System.Windows.Controls.Primitives.DataGridColumnHeadersPresenter'.
How to solve this and how to achieve my datagrid's column style as in above link

WPF/Styles: Setting Property Values of Template Elements

Suppose I have a style like
<Style x:Key="NotificationItemTemplate" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<DockPanel LastChildFill="False">
<DockPanel.Background>
<LinearGradientBrush>
<GradientStop Offset="0" Color="#FF565656" /> <!-- How to change color values -->
<GradientStop Offset="1" Color="#FF353535" />
</LinearGradientBrush>
</DockPanel.Background>
...
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I set the color value of a gradient stop as labeled above to a different color, say on MouseOver, I know I use a Trigger, but how do I refer to that color value?
Unfortunately, I'm not sure if you can do it for a single gradient stop. You likely have to trigger to change the entire background brush:
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<DockPanel LastChildFill="False" x:Name="dock">
<DockPanel.Background>
<LinearGradientBrush>
<GradientStop Offset="0" Color="#FF565656" />
<!-- How to change color values -->
<GradientStop Offset="1" Color="#FF353535" />
</LinearGradientBrush>
</DockPanel.Background>
<ContentPresenter />
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="dock" Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0" Color="#00CDFFFF" />
<!-- How to change color values -->
<GradientStop Offset="1" Color="#FF343465" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

ProgressBar clips the very top of value

I'm having a slight problem with reskinning a ProgressBar in WPF. Specifically, no matter what I do, it seems to clip the inner indicator at about 99%. I've tried all sorts of things, from clipping to OpacityMask, but I can't seem to stop the top from cutting off. Any ideas what's going on here?
Code:
<Style x:Key="BarrelStyle" TargetType="{x:Type ProgressBar}">
<Setter Property="Value" Value="100" />
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid>
<Border CornerRadius="10" BorderThickness="1" Padding="3,3,3,3" x:Name="PART_Track" Background="Blue">
<Border x:Name="PART_Indicator" CornerRadius="10" BorderBrush="#FFC06565" BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
<Grid>
<Border x:Name="Indicator_Content" CornerRadius="10" Background="Red" BorderBrush="White" BorderThickness="1"/>
<Border x:Name="Indicator_Gloss" CornerRadius="10" >
<Border.Background>
<LinearGradientBrush EndPoint="1.0,0.5" StartPoint="0.05,0.5">
<GradientStop Color="#75000000" Offset="0"/>
<GradientStop Color="#7EFFFFFF" Offset="0.5"/>
<GradientStop Color="#75000000" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</Border>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try setting inner most Grid's Margin="0,4" and set "PART_Indicator" Margin="0,0,0,-4". Or just use the code below:
<Style x:Key="BarrelStyle" TargetType="{x:Type ProgressBar}">
<Setter Property="Value" Value="100" />
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid>
<Border CornerRadius="10" BorderThickness="1" Padding="3,3,3,3" x:Name="PART_Track" Background="Blue">
<Border x:Name="PART_Indicator" CornerRadius="10" BorderBrush="#FFC06565" BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="0,0,0,-4">
<Grid Margin="0,4">
<Border x:Name="Indicator_Content" CornerRadius="10" Background="Red" BorderBrush="White" BorderThickness="1"/>
<Border x:Name="Indicator_Gloss" CornerRadius="10" >
<Border.Background>
<LinearGradientBrush EndPoint="1.0,0.5" StartPoint="0.05,0.5">
<GradientStop Color="#75000000" Offset="0"/>
<GradientStop Color="#7EFFFFFF" Offset="0.5"/>
<GradientStop Color="#75000000" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</Border>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to change control template from Style.Triggers

I've done it this way:
<Style x:Key="Button" BasedOn="{StaticResource LoginButton}" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border CornerRadius="4">
<Border.Background>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="0" Color="#0863a5" />
<GradientStop Offset="1" Color="#00457d" />
</LinearGradientBrush>
</Border.Background>
</Border>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border CornerRadius="4">
<Border.Background>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="0" Color="#508fbd" />
<GradientStop Offset="1" Color="#397ab0" />
</LinearGradientBrush>
</Border.Background>
</Border>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Is there any better way to do this? I've scenarios where my control template is having more lines of code, and I'd only require to change a single style like BorderBrush or something. How can I change control template from Style.Triggers efficiently?
If your intention is just to give a different Background to the Border. You can achieve this in the ControlTemplate.Triggers
<Style x:Key="Button" BasedOn="{StaticResource LoginButton}" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate >
<Grid>
<Border x:Name="brd" CornerRadius="4">
<Border.Background>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="0" Color="#0863a5" />
<GradientStop Offset="1" Color="#00457d" />
</LinearGradientBrush>
</Border.Background>
</Border>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="brd">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="0" Color="#508fbd" />
<GradientStop Offset="1" Color="#397ab0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources