我已经在WPF中实现了仪表控件作为自定义控件。它运行得很好,但是我遇到了一个问题,这使我怀疑它的结构是否正确。
使用不同的控制模板,我可以给仪表提供根本不同的样式,例如速度表,电压表,温度计或油位。
顶级仪表盘控件包含“范围”和“指针”两个集合。
范围定义了刻度上的彩色区域。这是一个具有一些属性的简单对象。
一个指针,很明显,在量规上定义了一个指针。一个指针可以有多个指针,并且指针可以具有不同的样式,例如针,彩色块或滑块(用户可以拖动)。
这是一个示例配置:
<gauge:Gauge MinValue="0"
MaxValue="350"
MajorDivisions="7"
MinorDivisions="5"
Caption="Bar"
Background="White"
LabelOrientation="Horizontal"
BorderThickness="3"
StartAngle="-180"
EndAngle="135"
MinorTickMarkColor="Black"
MajorTickMarkColor="Black"
LabelsOnTicks="Even"
LabelRadiusRelative="0.65"
Template="{StaticResource DefaultRotaryGauge}" >
<gauge:Gauge.Ranges>
<gauge:Range MinValue="200" MaxValue="350" Color="Green"/>
</gauge:Gauge.Ranges>
<gauge:Gauge.Pointers>
<gauge:Pointer Position="{Binding Position1}" ShowNumericValue="Visible" Color="LightGray"/>
<gauge:Pointer Position="{Binding Position2}" ShowNumericValue="Visible" Color="Red"/>
</gauge:Gauge.Pointers>
<gauge:Gauge.LabelStyle>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</gauge:Gauge.LabelStyle>
</gauge:Gauge>
如上所示,指针位置必须与绑定一起使用,因此它必须是依赖项属性,据我所知,它必须位于可视树中。
为此,将指针类定义为控件。
量规的控件模板使用ItemsControl来包含指针。每个指针都有其自己的控制模板,但是由于指针的样式不同,因此我使用触发器来为指针选择几种不同的模板之一。
例如,我的温度计控件模板支持两种指针样式,如下所示。
<ItemsControl ItemsSource="{TemplateBinding Pointers}"
Grid.Row="2"
Grid.Column="3"
ItemsPanel="{StaticResource GridTemplate}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="local:Pointer">
<Setter Property="Control.Template" Value="{StaticResource ThermometerPointer}"/>
<Style.Triggers>
<Trigger Property="DisplayStyle" Value="Block">
<Setter Property="Control.Template" Value="{StaticResource ThermometerBlock}"/>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
到目前为止很好。
现在我有一个要求,当该值超过给定阈值时,更改温度计中液体的颜色。当我尝试使用DataTrigger实现此功能时,
<gauge:Pointer Position="{Binding Position1}" DisplayStyle="Block">
<gauge:Pointer.Style>
<Style TargetType="gauge:Pointer">
<Setter Property="Color" Value="Red"/>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource GreaterThanConverter}">
<Binding Path="Position1"/>
<Binding Source="200.0"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Color" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</gauge:Pointer.Style>
</gauge:Pointer>
指针完全失去作用,因为它失去了与控制模板的连接。
除了DataTrigger之外,我还可以通过指定Control.Template来修复它。
<gauge:Pointer Position="{Binding Position1}" DisplayStyle="Block">
<gauge:Pointer.Style>
<Style TargetType="gauge:Pointer">
<Setter Property="Control.Template" Value="{StaticResource ThermometerBlock}"/>
<Setter Property="Color" Value="Red"/>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource GreaterThanConverter}">
<Binding Path="Position1"/>
<Binding Source="200.0"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Color" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</gauge:Pointer.Style>
</gauge:Pointer>
这有效,但是我对此不满意。量规控件的用户无法了解有关内部实现的详细信息。
我认为,对量规控件的控件模板定义指针的样式可能是不好的做法。我的问题是我想不出另一种方法来为指针选择不同的控制模板。
我认为我可以使用转换器来选择控件模板(将DisplayStyle属性转换为ControlTemplate),但是我可以看到在哪里应用转换器。
我唯一的另一种想法是摆脱DisplayStyle属性,而是定义从一个通用基指针类派生的多个指针类。然后,我可以为每个派生的指针类定义单独的控制模板。
我有几个问题。
首先,我这样做正确吗? 将指针定义为具有自己的控件模板的控件甚至有意义吗?
第二,有没有一种方法可以选择指针的控制模板,而无需样式定义?
如果没有,派生类的想法是否可行?