如何动态设置DataTrigger XAML的路径

时间:2015-03-25 17:06:01

标签: c# wpf xaml datatrigger mshtml

我有几个按钮,它们将共享一个共同的样式,它们都将具有基于绑定属性的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>

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

<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);
            }
        }
}

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

如果你想看到我可以给你看的窗口代码,否则这里是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更改

希望有所帮助。

谢谢!

2 个答案:

答案 0 :(得分:2)

由于您只能在DependencyProperties上设置绑定,并且Binding对象的Path属性不是DependencyProperty,因此您无法在此处实现此类事情。

在您的情况下,我强烈建议您使用自定义附加属性。 (这是一种可以附加到任何对象的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,但如果可以的话,我会建议更具描述性的内容。

答案 1 :(得分:0)

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