原文:WPF自定义控件(四)の自定义控件
在实际工作中,WPF提供的控件并不能完全满足不同的设计需求。这时,需要我们设计自定义控件。
这里LZ总结一些自己的思路,特性如下:
CouplingUITemplateBehaviourFunction Package
下面举例说说在项目中我们经常用到调音台音量条,写一个自定义控件模拟调音台音量条。
自定义控件SingnalLight,实现功能
接收来自外部的范围0~100的数值实时显示接收数值数值范围0~50显示绿色,50~85显示黄色,85~100显示红色,没有数值显示褐色可在父控件上拖拽该控件
public class SingnalLight : ContentControl {public int ValueA {get { return (int)GetValue(ValueAProperty); }set { SetValue(ValueAProperty, value); }}public SingnalLight() {this.AllowDrop = true;}static SingnalLight() {DefaultStyleKeyProperty.OverrideMetadata(typeof(SingnalLight), new FrameworkPropertyMetadata(typeof(SingnalLight)));}}
ValueA为接受外部数值的属性
2.复写控件UITemplate
1 <Style TargetType="{x:Type control:SingnalLight}">2 <Setter Property="RenderTransform">3 <Setter.Value>4 <TranslateTransform X="{Binding Path=X,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"5 Y="{Binding Path=Y,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"/>6 </Setter.Value>7 </Setter>8 <Setter Property="Template">9 <Setter.Value>10 <ControlTemplate>11 <ControlTemplate.Resources>12<control:SingnalLightStatusConverter x:Key="colorconverter"></control:SingnalLightStatusConverter>13<control:SingnalLightValueConverter x:Key="valueconverter"></control:SingnalLightValueConverter>14 </ControlTemplate.Resources>15 <StackPanel>16<TextBlock Text="{Binding Path=ValueA,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"></TextBlock>17<TextBlock Text="100"></TextBlock>18<Border 19 x:Name="bd1"20 Height="{Binding Path=LightHeight,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"21 SnapsToDevicePixels="True"22 BorderBrush="Black" BorderThickness="1" Background="Transparent">23 <Rectangle Fill="{Binding Path=ValueA,24RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}},25Converter={StaticResource ResourceKey=colorconverter}}" 26VerticalAlignment="Bottom">27 <Rectangle.Height>28 <MultiBinding Converter="{StaticResource ResourceKey=valueconverter}">29 <Binding Path="ValueA" RelativeSource="{RelativeSource AncestorType={x:Type control:SingnalLight}}"></Binding>30 <Binding Path="Height" ElementName="bd1"></Binding>31 </MultiBinding>32 </Rectangle.Height>33 </Rectangle>34</Border>35<TextBlock Text="0"></TextBlock>36 </StackPanel>37 </ControlTemplate>38 </Setter.Value>39 </Setter>40</Style>
3.接受值判断,SingnalLight通过实现IValueConverter和Override Arrange & Measure Methods,实现了UI呈现的绑定,
1public class SingnalLightStatusConverter : IValueConverter {2 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {3 SolidColorBrush result = Brushes.Transparent;4 if (value.GetType() == typeof(int)) {5 var color = System.Convert.ToInt32(value);6 if (color < 50) result = Brushes.Green;7 else if (color < 85 && color >= 50) result = Brushes.Yellow;8 else if (color <= 100 && color >= 85) result = Brushes.Red;9 else result = Brushes.Gray;10 }11 return result;12 }13 14 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {15 throw new NotImplementedException();16 }17}18 19public class SingnalLightValueConverter : IMultiValueConverter {20 public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {21 double result = 0;22 if (values[0].GetType() == typeof(int) && values[1].GetType() == typeof(double)) {23 result = (double)values[1] / 100 * System.Convert.ToDouble(values[0]);24 }25 return result;26 }27 28 public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {29 throw new NotImplementedException();30 }31}
1 protected override Size MeasureOverride(Size constraint) {2 if (ActualHeight > 0) LightHeight = ActualHeight * .7;3 return base.MeasureOverride(constraint);4 }5 6 protected override Size ArrangeOverride(Size arrangeBounds) {7 return base.ArrangeOverride(arrangeBounds);8 }
4.控件支持拖拽,覆写MouseDown,MouseMove,MouseUp方法。这样写的好处是,如果在父控件的事件中实现Drag,父控件如果有多个对象,这样逻辑会十分混乱。
1 protected override void OnMouseMove(MouseEventArgs e) {2 base.OnMouseMove(e);3 if (e.LeftButton == MouseButtonState.Pressed) {4 _currentPoint = e.GetPosition(this);5 X += _currentPoint.X - _startPoint.X;6 Y += _currentPoint.Y - _startPoint.Y;7 }8 }9 10 protected override void OnMouseDown(MouseButtonEventArgs e) {11 base.OnMouseDown(e);12 _startPoint = e.GetPosition(this);13 this.CaptureMouse();14 }15 16 protected override void OnMouseUp(MouseButtonEventArgs e) {17 base.OnMouseUp(e);18 this.ReleaseMouseCapture();19 }
自定义控件系列博文链接:
WPF自定义控件(一)の控件分类
WPF自定义控件(二)の重写原生控件样式模板
WPF自定义控件(三)の扩展控件
WPF自定义控件(四)の自定义控件
WPF自定义控件(五)の用户控件