ControlTemplate 在 Blend 中正常工作但在实际应用程序中不正确
ControlTemplate working correctly in Blend but not in actual application
我创建了一个自定义按钮,没什么特别的,只是 mahApps SquareButton 的扩展,左侧有一个小彩色标记。
我在 Blend 中设计它,并在 Visual Studio 中将代码复制到我的实际应用程序中。在 Blend 中启动时它工作得很好,在 Visual Studio 中启动时标记不可见并且文本左对齐,按钮看起来几乎像一个普通的 SquareButton。我做错了什么?
我把XAML复制自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>
只是按钮的自定义部分:
<Rectangle Fill="#FFAA2222" HorizontalAlignment="Left" Width="15" Margin="{Binding BorderThickness, ElementName=Background}" StrokeThickness="0" IsHitTestVisible="False"/>
以及我将其放入 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>
然后我使用了这样的按钮:
<view:MarkerButton MarkerColor="{Binding Color}" Content="{Binding Name}" MarkerWidth="15" .... />
使用 Punker76 的扩展按钮解决方案,我得到了这个:
定位错了,不过xaml好像是对的....
修复了我的旧解决方案,问题是我的宽度:我将其声明为 uint 而不是 double。不过,该按钮看起来与普通方形样式不同(不同的边框、焦点矩形、文本对齐方式),我不知道为什么。
首先你给我们看这个
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type Button}">
然后这个
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type view:MarkerButton}">
如果 MarkerButton
是一个按钮,那么如果您使用第一个针对该按钮的样式,这应该可以工作
<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" />
编辑
您还可以使用附加属性和继承样式来代替创建新按钮 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);
}
}
用法
<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}" />
您现在可以像这样在 XAML 中更改颜色
<Button Content="Test" ButtonsHelper.MarkerColor="YellowGreen" />
我创建了一个自定义按钮,没什么特别的,只是 mahApps SquareButton 的扩展,左侧有一个小彩色标记。
我在 Blend 中设计它,并在 Visual Studio 中将代码复制到我的实际应用程序中。在 Blend 中启动时它工作得很好,在 Visual Studio 中启动时标记不可见并且文本左对齐,按钮看起来几乎像一个普通的 SquareButton。我做错了什么?
我把XAML复制自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>
只是按钮的自定义部分:
<Rectangle Fill="#FFAA2222" HorizontalAlignment="Left" Width="15" Margin="{Binding BorderThickness, ElementName=Background}" StrokeThickness="0" IsHitTestVisible="False"/>
以及我将其放入 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>
然后我使用了这样的按钮:
<view:MarkerButton MarkerColor="{Binding Color}" Content="{Binding Name}" MarkerWidth="15" .... />
使用 Punker76 的扩展按钮解决方案,我得到了这个:
定位错了,不过xaml好像是对的....
修复了我的旧解决方案,问题是我的宽度:我将其声明为 uint 而不是 double。不过,该按钮看起来与普通方形样式不同(不同的边框、焦点矩形、文本对齐方式),我不知道为什么。
首先你给我们看这个
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type Button}">
然后这个
<Style x:Key="MarkerButtonStyle" TargetType="{x:Type view:MarkerButton}">
如果 MarkerButton
是一个按钮,那么如果您使用第一个针对该按钮的样式,这应该可以工作
<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" />
编辑
您还可以使用附加属性和继承样式来代替创建新按钮 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);
}
}
用法
<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}" />
您现在可以像这样在 XAML 中更改颜色
<Button Content="Test" ButtonsHelper.MarkerColor="YellowGreen" />