C# 如何动态设置DataTrigger XAML的路径

C# 如何动态设置DataTrigger XAML的路径,c#,wpf,xaml,datatrigger,mshtml,C#,Wpf,Xaml,Datatrigger,Mshtml,我有几个按钮将共享一个共同的样式,它们都将有基于绑定属性的DataTriggers。我试图避免为每个按钮写出每个datatrigger,所以我想知道是否有一种方法可以动态指定datatrigger.Binding的路径 例如: <DataTrigger Binding="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path={Binding RelativeSourc

我有几个按钮将共享一个共同的样式,它们都将有基于绑定属性的DataTriggers。我试图避免为每个按钮写出每个datatrigger,所以我想知道是否有一种方法可以动态指定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\u 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);
        }
按钮单击事件中显示的
“CurrentStyle”
根据布尔属性中的True或False进行更改

希望有帮助


谢谢

您不能为每个datatrigger编写一个样式,然后指向该样式吗?

由于您只能在DependencyProperties上设置绑定,并且绑定对象的
路径
属性不是
DependencyProperty
,所以您在这里实现了这种功能

在您的情况下,我强烈建议您创建一个自定义的附加属性以供使用。(这是一种可以附加到任何对象的DependencyProperty,而不仅仅是特定对象)

例如:

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

//这里的二传手



它还有一个额外的优势,即允许您为您的物业指定一个描述性名称,让其他开发人员清楚地了解该物业的用途和使用方式。我在这里使用了
DefaultButtonTriggerProperty
,但如果可以的话,我建议您使用更具描述性的属性。

如果没有这一点,就很难或不可能提供一个好的答案。当然,不能对路径使用
{Binding}
,因为它不是依赖属性。您可能可以编写代码,根据正在使用的
标记
属性动态创建绑定,也可能绑定到可以动态更新的代理对象。如果没有一个好的代码示例,就不可能提供关于这些可能性的具体细节。虽然不完整,但我添加了更多信息以帮助解决问题。在这一点上有很多代码需要处理,所以我可能最终用C#来完成,这正是我想要避免的。我正在寻找一个完整的XAML解决方案。您的代码有点混乱(例如,如果您正在设置Button.Tag,为什么要绑定到Window.Tag?),但据我所知,我将创建一个自定义的
DependencyProperty
,用于存储触发器基于的值。对于未来的开发人员来说,理解正在发生的事情会容易得多,而且如果您想要为您的样式提供多个动态值,它的可扩展性会更好。@Carson啊,我现在对您的绑定有了更多的了解。它是无效的,所以我很困惑。您正在使用绑定的
source
属性将绑定的源设置为
对象,并尝试将
Path
属性设置为另一个绑定值(
{Self}.Tag
)。因此,您的示例中的代码将解析为尝试绑定到
Window.IsBold
,如果这样做有效的话。但它不是,因为您只能绑定到
dependencProperty
,并且绑定的
Path
属性不是dependencProperty。为此,我强烈推荐定制DP:)@Carson好的,我在下面添加了一个示例,以及一个简短的XAML示例:)您不能在
中设置
样式
属性
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);
            }
        }
}
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);
        }
<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}" ... />