如何动态设置 DataTrigger XAML 的路径

How can I dynamically set the path of a DataTrigger XAML

我有几个共享相同样式的按钮,它们都将具有基于绑定 属性 的 DataTriggers。我试图避免为每个按钮写出每个数据触发器,所以我想知道是否有办法动态指定 DataTrigger.Binding?

的路径

例如:

<DataTrigger 
Binding="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, 
Path={Binding RelativeSource={RelativeSource Self}, Path=Tag}}" Value="True">
        <!--Do Something-->
</DataTrigger>

我知道这可能不可能,但我想我会试一试。我将 属性 名称存储为每个按钮上的标签,并且 属性 应该在单击时更改。所以我想使用存储在标签名称中的值作为默认样式的数据触发器上的路径。这是一个将一些文本加粗的示例按钮:

<Button Content="B" Tag="IsBold" Click="Button_Click" Style="{StaticResource DefaultButton}"/>

这是使用的样式:

<Style TargetType="{x:Type Button}" x:Key="DefaultButton">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Width" Value="20"/>
            <Setter Property="Height" Value="20"/>
            <Setter Property="Margin" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Background="{TemplateBinding Background}" 
                                BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" Padding="2" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="LightBlue"/>
                    <Setter Property="BorderBrush" Value="Blue"/>
                </Trigger>
                <DataTrigger Binding="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path={Binding RelativeSource={RelativeSource Self}, Path=Tag}}" Value="True">

                </DataTrigger>
            </Style.Triggers>
        </Style>

很明显,由于DataTrigger,样式暂时无效。有什么方法可以使这种事情完全动态化,还是我必须绑定每个按钮?

我尝试过使用 ValueConverters,但我认为它们不会起作用,因为它们只在初始化时触发一次。

更新更多信息:

我有一个数据对象作为一种视图。出于所有意图和目的,假设这就是它的全部内容:

using System;
using mshtml;
using System.Windows.Controls;
using System.Windows.Media;
using System.Reflection;
using System.ComponentModel;

namespace Aspen.Visuals
{
    public class HtmlFormattingExecutor : INotifyPropertyChanged
    {
        public HtmlFormattingExecutor(HTMLDocument doc)
        {
             this.doc = doc;
             this.isBold = false;
        }
        private HTMLDocument doc;
        private Boolean isBold;

        public Boolean IsBold { 
            get {return this.isBold;}
            set
            {
                if(this.isBold != value)
                {
                     this.isBold = value;
                     this.Bold();
                     this.NotifyPropertyChanged("IsBold");
                }
            }
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        private void Bold()
        {
            if (doc != null)
            {
                doc.execCommand("Bold", false, null);
            }
        }
}

该对象设置为具有先前显示的按钮和样式的 window 的数据上下文。

如果您想查看 window 代码,我可以给您看,否则这里是 button_click 事件的代码

private void Button_Click(Object sender, RoutedEventArgs e)
        {
            Button button = e.Source as Button;
            if (button != null)
            {
                this.AlterButtonStyle(button.Tag as String);
                button.Style = (Style)(Window.GetWindow(button).TryFindResource("CurrentStyle"));
            }
        }

private void AlterButtonStyle(String propertyName)
        {
            if (String.IsNullOrWhiteSpace(propertyName)) return;
            PropertyInfo info = this.formatting.GetType().GetProperty(propertyName);
            if (info == null || info.PropertyType != typeof(Boolean)) return;
            info.SetValue(this.formatting, !(Boolean)info.GetValue(this.formatting, null), null);
        }

Button_Click 事件中显示的 "CurrentStyle" 根据布尔值 属性

中的 True 或 False 而变化

希望对您有所帮助。

谢谢!

你不能为每个数据触发器写一个样式然后指向那个样式吗?

这种事情是不可能的,因为你在这里实现了,因为你只能在 DependencyProperties 上设置绑定,而 Binding 对象的 Path 属性 不是 DependencyProperty .

对于您的情况,我强烈建议您制作一个自定义附件 属性 以供使用。 (它是一种依赖属性,可以附加到任何对象,而不仅仅是特定的对象)

例如:

<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(local:CustomProperties.DefaultButtonTriggerProperty)}" 
                 Value="True">
        // setters here
    </DataTrigger>
</DataTemplate.Triggers>

<Button local:CustomProperties.DefaultButtonTriggerProperty="IsBold" 
        Style="{StaticResource DefaultButton}" ... />

它还有一个额外的好处,就是允许您为 属性 起一个描述性名称,让其他开发人员清楚 属性 的用途和使用方式。我在这里使用了 DefaultButtonTriggerProperty,但如果可以的话,我会推荐更具描述性的内容。