Reputation: 1502
I created a custom button, nothing too fancy, just an extension of the mahApps SquareButton with a little colored marker at the left side.
I designed it in Blend, and copied the code into my real application in Visual Studio. When starting in Blend it's working just fine, when starting in Visual Studio the marker is not visible and also the Text gets left aligned, the button is looking nearly like a normal SquareButton. What am I doing wrong?
The XAML I put copied from Blend:
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type Button}">
<Setter Property="MinHeight" Value="25"/>
<Setter Property="FontFamily" Value="{DynamicResource DefaultFont}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Background" Value="{DynamicResource WhiteBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BlackBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Padding" Value="5,6"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement">
<SplineDoubleKeyFrame KeyTime="0" Value="0.7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PART_ContentPresenter">
<EasingDoubleKeyFrame KeyTime="0" Value="0.3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid"/>
<VisualState x:Name="InvalidFocused"/>
<VisualState x:Name="InvalidUnfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{x:Null}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Rectangle Fill="#FFAA2222" HorizontalAlignment="Left" Width="15" Margin="{Binding BorderThickness, ElementName=Background}" StrokeThickness="0" IsHitTestVisible="False"/>
<Rectangle x:Name="DisabledVisualElement" Fill="{DynamicResource ControlsDisabledBrush}" IsHitTestVisible="False" Opacity="0"/>
<Custom:ContentControlEx x:Name="PART_ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource GrayBrush8}"/>
<Setter Property="Foreground" Value="{DynamicResource BlackBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{DynamicResource BlackBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource WhiteBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just the custom part of the button:
<Rectangle Fill="#FFAA2222" HorizontalAlignment="Left" Width="15" Margin="{Binding BorderThickness, ElementName=Background}" StrokeThickness="0" IsHitTestVisible="False"/>
And the code i put around to get it into VS:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:view="clr-namespace:MyApplication.View">
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type view:MarkerButton}">
...
</Style>
<Style TargetType="{x:Type view:MarkerButton}" BasedOn="{StaticResource MarkerButtonStyle}"/>
</ResourceDictionary>
Then I used the button like this:
<view:MarkerButton MarkerColor="{Binding Color}" Content="{Binding Name}" MarkerWidth="15" .... />
With Punker76's solution of extending the button I get this:
The positioning is broken, but the xaml seems to be right....
Fixed my old solution, the problem was my width: I declared it as uint instead of double. Still, the button appears different to the normal square style (different border, focus rect, text alignment) and I don't know why.
Upvotes: 0
Views: 45
Reputation: 14611
First you show us this
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type Button}">
And then this
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type view:MarkerButton}">
If the MarkerButton
is a button, then this should work if you use the first style that targets to the Button
<Style TargetType="{x:Type view:MarkerButton}"
BasedOn="{StaticResource MarkerButtonStyle}">
<Setter Property="MarkerColor" Value="#FFAA2222" />
<Setter Property="MarkerWidth" Value="15" />
</Style>
<Button Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" />
EDIT
You can also use attached properties and inherited style instead createing a new button class.
public static class ButtonsHelper
{
public static readonly DependencyProperty MarkerColorProperty
= DependencyProperty.RegisterAttached("MarkerColor", typeof(Brush), typeof(ButtonsHelper), new FrameworkPropertyMetadata(Brushes.Transparent));
public static void SetMarkerColor(DependencyObject obj, Brush value)
{
obj.SetValue(MarkerColorProperty, value);
}
public static Brush GetMarkerColor(DependencyObject obj)
{
return (Brush)obj.GetValue(MarkerColorProperty);
}
public static readonly DependencyProperty MarkerWidthProperty
= DependencyProperty.RegisterAttached("MarkerWidth", typeof(double), typeof(ButtonsHelper), new FrameworkPropertyMetadata(15d));
public static void SetMarkerWidth(DependencyObject obj, double value)
{
obj.SetValue(MarkerWidthProperty, value);
}
public static double GetMarkerWidth(DependencyObject obj)
{
return (double)obj.GetValue(MarkerWidthProperty);
}
}
usage
<Style x:Key="MarkerButtonStyle" BasedOn="{StaticResource SquareButtonStyle}" TargetType="{x:Type Button}">
<Setter Property="ButtonsHelper.MarkerColor" Value="#FFAA2222"/>
<Setter Property="ButtonsHelper.MarkerWidth" Value="15"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Rectangle Width="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=(ButtonsHelper.MarkerWidth), Mode=OneWay}"
HorizontalAlignment="Left"
Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=(ButtonsHelper.MarkerColor), Mode=OneWay}"
IsHitTestVisible="False"
StrokeThickness="0" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Mode=OneWay}" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource MarkerButtonStyle}" TargetType="{x:Type Button}" />
You can now change your color in XAML like this
<Button Content="Test" ButtonsHelper.MarkerColor="YellowGreen" />
Upvotes: 1