我正在尝试设计一组显示设备级别的控件。
我正在使用具有多数据触发器样式的标签控件,该触发器检查该字段的值是否在某个值之间,并应用突出显示以指示错误。
<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>
我试图解决的问题是通常有两种或三种状态:正常、警告和错误。这些状态适用于多个领域。
我希望能够将触发器的设置器合并到一个可以单独存储的静态资源中,比如一个列表,然后简单地使用这个列表作为 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 属性没有设置方法,并且需要触发器来确定状态。
有什么办法可以完成我想要的吗?
可能的解决方案:
- 一个接受范围列表并应用正确样式的控件
- 将设置器从一个触发器复制/粘贴到另一个*当前使用此 *
- @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}"/>