C#/ WPF - 共享样式设置器

时间:2015-03-28 20:19:54

标签: c# wpf datatrigger multidatatrigger wpf-style

我正在尝试设置一组显示设备级别的控件。

我正在使用一个带有多数据触发器样式的Label控件,该触发器检查该字段的值是否在某个值之间,并应用突出显示来指示错误。

<Style x:Key="highlight-stat" TargetType="Label">
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Value="True">
                    <Condition.Binding>
                        <MultiBinding Converter="{StaticResource BetweenValuesConverter}">
                            <Binding/>
                            <Binding>
                                <Binding.Source>
                                    <sys:Int32>100</sys:Int32>
                                </Binding.Source>
                            </Binding>
                            <Binding>
                                <Binding.Source>
                                    <sys:Int32>200</sys:Int32>
                                </Binding.Source>
                            </Binding>
                            <Binding>
                                <Binding.Source>
                                    <sys:Boolean>True</sys:Boolean>
                                </Binding.Source>
                            </Binding>
                            <Binding>
                                <Binding.Source>
                                    <sys:Boolean>False</sys:Boolean>
                                </Binding.Source>
                            </Binding>
                        </MultiBinding>
                    </Condition.Binding>
                </Condition>
            </MultiDataTrigger.Conditions>
            <MultiDataTrigger.Setters>
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="FontWeight" Value="Bold"/>
            </MultiDataTrigger.Setters>
    </Style.Triggers>
</Style>

我要解决的问题是通常有两种或三种状态:正常,警告和错误。这些状态适用于多个字段。

我希望能够将触发器的setter合并到一个静态资源中,我可以像List一样单独存储,只需使用此列表作为MultiDataTrigger.Setters的值。通过这种方式,我可以将错误和警告状态定义为setter的集合,并从中心位置更新它们。

IE:

<Style x:Key="error-state" TargetType="Control">
    <Setter Property="Foreground" Value="Red"/>
    <Setter Property="Background" Value="White"/>
    <Setter Property="FontWeight" Value="Bold"/>
</Style>
<Style x:Key="warning-state" TargetType="Control">
    <Setter Property="Background" Value="Yellow"/>
</Style>

我遇到的问题是DataTrigger / MultiDataTrigger的Setters属性没有set方法,需要触发器来确定状态。

有什么方法可以达到我的目的吗?

可能的解决方案:

  • 接受范围列表并应用正确样式的控件
  • 将设置者从一个触发器复制/粘贴到另一个 *当前正在使用此
  • @PieterWitvoet推荐StyleSelector

修改

我已经创建了一个用户控件来完成我想要的。 C#

public class Label : System.Windows.Controls.Label, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Label()
    {
        var metadata = ContentProperty.GetMetadata(this);
        ContentProperty.OverrideMetadata(typeof(Label), new FrameworkPropertyMetadata(propertyChanged));

        Rules = new List<HighlightingRule>();
        PropertyChanged += (o, a) =>
        {
            System.Diagnostics.Debug.WriteLine(string.Format("#triggered - {0}", a.PropertyName));
        };
    }

    /// <summary>
    /// Gets or sets the highlighting rules applied by this control
    /// </summary>
    public List<HighlightingRule> Rules { get; set; }

    static void propertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
    {
        if (o is Label)
        {
            (o as Label).reapplyRules();
        }
    }


    void reapplyRules()
    {
        Style = null;
        foreach (var rule in Rules)
        {
            if (rule.IsMatch(Content))
            {
                Style = rule.MatchStyle;
                break;
            }
        }
    }
}

我正在使用以下基类来定义规则

/// <summary>
/// Base Class for Highlighting rules used by HighlightedLabel
/// </summary>
public abstract class HighlightingRule
{
    public Style MatchStyle { get; set; }

    public virtual bool IsMatch(object value)
    {
        return false;
    }
}

例如:

public class UnderValueRule : HighlightingRule
{
    public double Value { get; set; }
    public bool Inclusive { get; set; }

    public override bool IsMatch(object value)
    {
        if (value is int || value is double)
        {
            double dValue = Convert.ToDouble(value);
            return dValue.CompareTo(Value) <= (Inclusive ? 0 : -1);
        }
        else if (value is decimal)
        {
            decimal dValue = Convert.ToDecimal(value);
            return dValue.CompareTo(Convert.ToDecimal(Value)) <= (Inclusive ? 0 : -1);
        }
        return false;
    }
}

在XAML中:

<rules:UnderValueRule Value="31" Inclusive="False" MatchStyle="{StaticResource error-state}"/>

0 个答案:

没有答案