zoukankan      html  css  js  c++  java
  • WPF自定义控件(四)の自定义控件

    在实际工作中,WPF提供的控件并不能完全满足不同的设计需求。这时,需要我们设计自定义控件。

    这里LZ总结一些自己的思路,特性如下:

    • Coupling
    • UITemplate
    • Behaviour
    • Function 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,
    24                                                       RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}},
    25                                                       Converter={StaticResource ResourceKey=colorconverter}}" 
    26                                        VerticalAlignment="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呈现的绑定,

     1     public 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 
    19     public 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自定义控件(五)の用户控件

  • 相关阅读:
    Codeforces 每日一练 1213G+961E+1282B2
    AtCoder Beginner Contest 161题解
    Codeforces每日一练 495B+55C+1280C
    CF1062E 线段树/LCA
    Codeforces Round #697 (Div. 3) 题解
    Codeforces Round #511 (Div. 2) A~D题解
    Atcoder ABC 189 题解
    CF1093G 高维曼哈顿距离/线段树
    CF1117D Magic Gems 矩阵快速幂 DP
    CF1106E Lunar New Year and Red Envelopes DP
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/7569337.html
Copyright © 2011-2022 走看看