Wpf 将路径填充绑定到ContentPresenter中的按钮前景
我有一个包含ContentPresenter的模板的按钮样式,其中我尝试将路径填充绑定到按钮的前景:Wpf 将路径填充绑定到ContentPresenter中的按钮前景,wpf,xaml,Wpf,Xaml,我有一个包含ContentPresenter的模板的按钮样式,其中我尝试将路径填充绑定到按钮的前景: <!-- This is inside the template of a button style --> <ContentPresenter> <ContentPresenter.Resources> <Style TargetType="{x:Type Path}"> <Setter Property="Fill" Valu
<!-- This is inside the template of a button style -->
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="{x:Type Path}">
<Setter Property="Fill" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=Button}}"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
我还有一个没有填充集的路径,我可以在按钮中引用它作为内容,如下所示:
<Button Style="{DynamicResource MyButtonStyle}" Content="{DynamicResource PathIcon}" Foreground="Blue"/>
我希望按钮内的路径是蓝色的,但它不是。。。它不能从按钮上抓取前景
如何获取绑定到按钮颜色的路径
谢谢大家!
附言:
如果我在值中添加了硬编码颜色(即Value=“Red”),则按钮内的路径为红色。。。所以我知道这很有效
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="{x:Type Path}">
<Setter Property="Fill" Value="Red"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
编辑: 以下是完整的样式和控件模板:
<Style x:Key="Button_Style" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="{StaticResource White_Brush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="grid" Background="Transparent">
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="{x:Type Path}">
<Setter Property="Fill" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=Button}}"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- Should affect Text as well as Paths in the Content property of the button! -->
<Setter Property="Foreground" Value="{StaticResource Black_Brush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
好的,我们来点:
它不能从按钮上抓取前景
在这种结构中:
RelativeSource={RelativeSource AncestorType=Button}
不会起作用,因为样式
只是setter的集合,他不知道如何控制,是否存在,特别是视觉树的内容。因为RelativeSource
应该引用可视化树中的上述项。为此,通常使用DataTemplate
或ControlTemplate
如果我在值中添加硬编码颜色(即Value=“Red”)
是的,在这种情况下,将起作用,并且总是更好地创建表单的设计:
<SolidColorBrush x:Key="MyButtonColor" Color="Blue" />
在样式中或其他地方:
<Setter Property="Fill" Value="{StaticResource MyButtonColor}" />
代码隐藏
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);
}
}
注意:
在样式中
我没有对attached属性使用TemplateBinding,因为TemplateBinding在模板外部或其VisualTree属性外部不起作用,所以您甚至不能在模板的触发器内部使用TemplateBinding。因此,我们必须使用构造{relativeSourceTemplatedParent}
和与要检索其值的依赖项属性相等的路径
输出
要下载整个示例,请按照此操作。我偶然发现了类似的问题,但想知道如何在按钮处于禁用状态时获得“前景色”(以获得正确的绘图颜色)。这里是最后一个简单的解决方案。没有模板,没有样式,没有代码,什么都没有。正是正确的相对绑定:-):
谢谢您的回复!这里有很多关于WPF最佳实践的好信息,但我不确定如何应用您的评论来解决我的问题。@user1084857:好的,那么您的问题是什么?我可能应该更清楚高级问题:我希望能够将文本块、路径或两者作为按钮的内容,并更改鼠标上方的颜色、显示等。。。无需管理大量状态列表作为数据触发器来强制设置路径的颜色。我想一个简单的方法是直接在样式/模板中为每个状态设置前景,然后我在内容上放置的任何路径都将获取前景的颜色。这就是我要做的…@user1084857:尝试将相对资源
移动到控制模板
,在那里它会工作,在风格
中它不会工作。我相信这就是我要做的。。。我在原来的问题中添加了完整的样式和控件模板。。。你觉得有什么不对劲吗?
<Window x:Class="ButtonPathHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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="{x:Type Button}">
<Setter Property="Foreground" Value="{StaticResource Green_Brush}" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="grid">
<ContentPresenter x:Name="MyContent"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}" />
<Path x:Name="MyPath"
SnapsToDevicePixels="True"
Width="20"
Height="18"
Stretch="Fill"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:MyDependencyClass.DataForPath)}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource Black_Brush}"/>
</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="{StaticResource Button_Style}"
Tag="OnlyPath"
local:MyDependencyClass.DataForPath="{StaticResource Save}"
Margin="10" />
<Button Name="JustText"
Style="{StaticResource Button_Style}"
Tag="OnlyText"
Content="Just Text"
Margin="10" />
<Button Name="SearchButton"
Style="{StaticResource Button_Style}"
Tag="OnlyPath"
local:MyDependencyClass.DataForPath="{StaticResource Search}"
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);
}
}
<StackPanel Orientation="Horizontal">
<Button Height="22" IsEnabled="False">
<Polygon Points="4,0 4,5 5,5 2.5,10 0,5 1,5 1,0 "
Fill="{Binding (TextElement.Foreground), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}}">
<Polygon.LayoutTransform>
<RotateTransform Angle="90"></RotateTransform>
</Polygon.LayoutTransform>
</Polygon>
</Button>
<Button Height="22" IsEnabled="True">
<Polygon Points="4,0 4,5 5,5 2.5,10 0,5 1,5 1,0 "
Fill="{Binding (TextElement.Foreground), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}}">
<Polygon.LayoutTransform>
<RotateTransform Angle="180"></RotateTransform>
</Polygon.LayoutTransform>
</Polygon>
</Button>
</StackPanel>