好的,让我们开始:
它无法从按钮中抓取前景。
在样式中,使用以下结构:
RelativeSource={RelativeSource AncestorType=Button}
因为Style
仅仅是一组属性集合,他并不知道控件是否存在,尤其是在视觉树中的内容。由于RelativeSource
应该引用视觉树中上面的项。为此,通常使用DataTemplate
或ControlTemplate
。
如果我在Value中放一个硬编码的颜色(即Value="Red")
是的,在这种情况下,将会工作,并且总是更好地创建表单的设计:
<SolidColorBrush x:Key="MyButtonColor" Color="Blue" />
您可以将其用于控制,例如按钮
:
<Button Background="{StaticResource MyButtonColor}" ... />
无论是在 Style
中还是其他地方:
<Setter Property="Fill" Value="{StaticResource MyButtonColor}" />
也就是说,最好不要依赖于可视树中的元素参数(背景颜色等),因为它可能会:
- 移动到另一个面板(
Grid
、StackPanel
)或UserControl
- 离开项目
而作为资源的画笔始终在一个位置,更改它们的位置,所有元素都将使用它们。此外,颜色可以存储在特殊的数据模型中,该数据模型不依赖于特定的技术实现(资源、变量),其中数据可以来自外部源,例如项目/配置设置。
如果可能的话,最好避免使用动态资源,因为这样会不必要地使用系统性能(并且在某些情况下会导致内存泄漏),在您的情况下不需要使用它们。
动态资源通常是显式定义为SolidColorBrush
和其他类型的画笔,因为默认情况下它们是被冻结的,并且不建议更改它们,因为上述原因(内存泄漏)。更多信息可以在此处找到:
MSDN上的Freezable对象概述
编辑
据我所了解,您想要为Button
创建通用的Style
,以使Path
或Text
的内容更容易(在同时使用时)。正如我之前提到的,RelativeSource
应该位于ControlTemplate
周围,因此,Path
将位于带有ContentPresenter
的Grid
中。
为了使样式知道是为文本还是路径提供的,Tag
(可选属性)指示两个属性:OnlyText
或OnlyPath
。
为了设置Path
的数据,我创建了一个附加依赖属性,并在ControlTemplate
中进行了规定。
以下是完整的示例:
XAML
<Window x:Class="ButtonPathHelp.MainWindow"
xmlns="http:
xmlns:x="http:
xmlns:local="clr-namespace:ButtonPathHelp"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="Green_Brush" Color="Green" />
<SolidColorBrush x:Key="Black_Brush" Color="Black" />
<Style x:Key="Button_Style" TargetType="">
<Setter Property="Foreground" Value="" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="">
<Grid x:Name="grid">
<ContentPresenter x:Name="MyContent"
Content=""
HorizontalAlignment=""
VerticalAlignment="" />
<Path x:Name="MyPath"
SnapsToDevicePixels="True"
Width="20"
Height="18"
Stretch="Fill"
Fill="}}"
Data=", Path=(local:MyDependencyClass.DataForPath)}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value=""/>
</Trigger>
<Trigger Property="Tag" Value="OnlyText">
<Setter TargetName="MyPath" Property="Visibility" Value="Collapsed" />
<Setter TargetName="MyContent" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="Tag" Value="OnlyPath">
<Setter TargetName="MyPath" Property="Visibility" Value="Visible" />
<Setter TargetName="MyContent" Property="Visibility" Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<WrapPanel>
<WrapPanel.Resources>
<sys:String x:Key="Save">
F1 M 20.5833,20.5833L 55.4167,20.5833L 55.4167,55.4167L 45.9167,55.4167L 45.9167,44.3333L 30.0833,44.3333L 30.0833,
55.4167L 20.5833,55.4167L 20.5833,20.5833 Z M 33.25,55.4167L 33.25,50.6667L 39.5833,50.6667L 39.5833,55.4167L 33.25,
55.4167 Z M 26.9167,23.75L 26.9167,33.25L 49.0833,33.25L 49.0833,23.75L 26.9167,23.75 Z
</sys:String>
<sys:String x:Key="Search">
F1 M 23.4454,49.2637L 31.7739,41.1598C 30.6986,39.2983 30.4792,37.1377 30.4792,34.8333C 30.4792,27.8377 35.7544,
22.1667 42.75,22.1667C 49.7456,22.1667 55.4167,27.8377 55.4167,34.8333C 55.4167,41.8289 49.7456,47.1042 42.75,
47.1042C 40.5639,47.1042 38.5072,46.9462 36.7125,45.9713L 28.3196,54.1379C 27.0829,55.3746 24.6821,55.3746 23.4454,
54.1379C 22.2088,52.9013 22.2088,50.5004 23.4454,49.2637 Z M 42.75,26.9167C 38.3777,26.9167 34.8333,30.4611 34.8333,
34.8333C 34.8333,39.2056 38.3777,42.75 42.75,42.75C 47.1222,42.75 50.6667,39.2056 50.6667,34.8333C 50.6667,
30.4611 47.1222,26.9167 42.75,26.9167 Z
</sys:String>
</WrapPanel.Resources>
<Button Name="SaveButton"
Style=""
Tag="OnlyPath"
local:MyDependencyClass.DataForPath=""
Margin="10" />
<Button Name="JustText"
Style=""
Tag="OnlyText"
Content="Just Text"
Margin="10" />
<Button Name="SearchButton"
Style=""
Tag="OnlyPath"
local:MyDependencyClass.DataForPath=""
Margin="10" />
</WrapPanel>
</Window>
后端代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class MyDependencyClass : DependencyObject
{
#region IsCheckedOnDataProperty
public static readonly DependencyProperty DataForPathProperty;
public static void SetDataForPath(DependencyObject DepObject, string value)
{
DepObject.SetValue(DataForPathProperty, value);
}
public static string GetDataForPath(DependencyObject DepObject)
{
return (string)DepObject.GetValue(DataForPathProperty);
}
#endregion
static MyDependencyClass()
{
PropertyMetadata MyPropertyMetadata = new PropertyMetadata(String.Empty);
DataForPathProperty = DependencyProperty.RegisterAttached("DataForPath",
typeof(string),
typeof(MyDependencyClass),
MyPropertyMetadata);
}
}
注意:在样式中,我没有使用TemplateBinding来绑定附加属性,因为TemplateBinding无法在模板外或其VisualTree属性外部工作,所以甚至不能在模板的触发器内使用TemplateBinding。因此,我们必须使用构造函数{RelativeSource TemplatedParent}和Path等于要检索其值的依赖属性。
输出
![enter image description here](https://istack.dev59.com/kvKbD.webp)
要下载整个示例,请使用此
链接。
RelativeSource
移动到ControlTemplate
中,它会起作用,在Style
中它不会起作用。 - Anatoliy NikolaevTag
来实现此目的。 - Anatoliy Nikolaev