zoukankan      html  css  js  c++  java
  • WPF自定义控件开发实例

    开发环境:Win10 + VS2017 + .Net4.5

    这个 ColorPicker 是<<WPF编程宝典:使用C#2012和.NET4.5>>这本书中的例子.这里我记录一下,主要是为了加深印象,防止以后要开发自定义控件的时候忘记一些基本的步骤,可以随时来查一下.
    调到博文的最后可以先查看一下效果图.

    1. 建立ColorPicker类继承自 Control

      为什么继承自 Control,Control类继承自UIElement -> FrameworkElement -> ColorPicker,同时 Control 类提供了 Template 功能.

    2. 通知WPF,将为控件提供新的样式.
      方法是在静态构造函数中调用 OverrideMetadata()方法.

      static ColorPicker()
       {
           DefaultStyleKeyProperty.OverrideMetadata(
               typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
       }
      
    3. 编写控件逻辑,添加一些必要的属性|事件|方法 ...

    4. 重写 OnApplyTemplate 方法,为模板中的元素添加数据绑定或者关联事件处理程序

    5. ColorPicker类的完整代码:

      using System;
       using System.Windows;
       using System.Windows.Controls;
       using System.Windows.Controls.Primitives;
       using System.Windows.Data;
       using System.Windows.Media;
      

      namespace Demo.DIYControl.Controls.DeepInDIY
      {
      [TemplatePart(Name = RedSliderName,Type = typeof(RangeBase))]
      [TemplatePart(Name = GreenSliderName, Type = typeof(RangeBase))]
      [TemplatePart(Name = BlueSliderName, Type = typeof(RangeBase))]
      [TemplatePart(Name = PreviewBrushName, Type = typeof(SolidColorBrush))]
      public class ColorPicker:Control
      {
      private const string RedSliderName = "PART_RedSlider";
      private const string GreenSliderName = "PART_GreenSlider";
      private const string BlueSliderName = "PART_BlueSlider";
      private const string PreviewBrushName = "PART_PreviewBrush";

           private Brush _initializeBorderBrush;
           
      
           public const byte RGBMaxValue = 255;
      
           public byte Red
           {
               get { return (byte)GetValue(RedProperty); }
               set { SetValue(RedProperty, value); }
           }
           // Using a DependencyProperty as the backing store for Red.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty RedProperty =
               DependencyProperty.Register(
                   nameof(Red), typeof(byte), typeof(ColorPicker), 
                   new FrameworkPropertyMetadata(OnColorRGBChanged));
      
           public byte Green
           {
               get { return (byte)GetValue(GreenProperty); }
               set { SetValue(GreenProperty, value); }
           }
           // Using a DependencyProperty as the backing store for Green.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty GreenProperty =
               DependencyProperty.Register(
                   nameof(Green), typeof(byte), typeof(ColorPicker), 
                   new FrameworkPropertyMetadata(OnColorRGBChanged));
      
           public byte Blue
           {
               get { return (byte)GetValue(BlueProperty); }
               set { SetValue(BlueProperty, value); }
           }
           // Using a DependencyProperty as the backing store for Blue.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty BlueProperty =
               DependencyProperty.Register(
                   nameof(Blue), typeof(byte), typeof(ColorPicker), 
                   new FrameworkPropertyMetadata(OnColorRGBChanged));
      
           public Color Color
           {
               get { return (Color)GetValue(ColorProperty); }
               set { SetValue(ColorProperty, value); }
           }
           // Using a DependencyProperty as the backing store for Color.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty ColorProperty =
               DependencyProperty.Register(nameof(Color), typeof(Color), 
                   typeof(ColorPicker), new FrameworkPropertyMetadata(Colors.Black,OnColorChanged));
      
           public CornerRadius CornerRadius
           {
               get { return (CornerRadius)GetValue(CornerRadiusProperty); }
               set { SetValue(CornerRadiusProperty, value); }
           }
           // Using a DependencyProperty as the backing store for CornerRadius.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty CornerRadiusProperty =
               DependencyProperty.Register(&quot;CornerRadius&quot;, typeof(CornerRadius), typeof(ColorPicker), 
                   new FrameworkPropertyMetadata(default(CornerRadius)));
      
           public bool UseDynamicBorder
           {
               get { return (bool)GetValue(UseDynamicBorderProperty); }
               set { SetValue(UseDynamicBorderProperty, value); }
           }
           // Using a DependencyProperty as the backing store for UseDynamicBorder.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty UseDynamicBorderProperty =
               DependencyProperty.Register(
                   &quot;UseDynamicBorder&quot;, typeof(bool), typeof(ColorPicker), 
                   new FrameworkPropertyMetadata(true, OnUseDynamicBorderChanged));
      
      
           public static readonly RoutedEvent ColorChangedEvent = EventManager.RegisterRoutedEvent(
               &quot;ColorChangedEvent&quot;, RoutingStrategy.Bubble,
               typeof(RoutedPropertyChangedEventHandler&lt;Color&gt;), typeof(ColorPicker));
           public event RoutedPropertyChangedEventHandler&lt;Color&gt; ColorChanged
           {
               add { AddHandler(ColorChangedEvent, value); }
               remove { RemoveHandler(ColorChangedEvent, value); }
           }
      
           static ColorPicker()
           {
               DefaultStyleKeyProperty.OverrideMetadata(
                   typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
           }
      
           public ColorPicker()
           {
               Loaded += (sender, args) =&gt;
               {
                   _initializeBorderBrush = BorderBrush;   //save initial borderbrush
                   BorderBrush = UseDynamicBorder? new SolidColorBrush(Color) : BorderBrush;
               };
           }
      
      
           private static void OnColorRGBChanged(DependencyObject sender,
               DependencyPropertyChangedEventArgs args)
           {
               ColorPicker colorPicker = sender as ColorPicker;
               colorPicker = colorPicker ?? throw new ArgumentException();
      
               Color color = colorPicker.Color;
               if (args.Property == RedProperty)
                   color.R = (byte)args.NewValue;
               else if (args.Property == GreenProperty)
                   color.G = (byte)args.NewValue;
               else if (args.Property == BlueProperty)
                   color.B = (byte)args.NewValue;
      
               colorPicker.Color = color;
           }
      
           private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
           {
               ColorPicker colorPicker = d as ColorPicker;
               d = d ?? throw new ArgumentException();
               colorPicker.Red = colorPicker.Color.R;
               colorPicker.Green = colorPicker.Color.G;
               colorPicker.Blue = colorPicker.Color.B;
      
               //set border color
               if (colorPicker.UseDynamicBorder)
                   colorPicker.BorderBrush = new SolidColorBrush(colorPicker.Color);
      
               colorPicker.RaiseEvent(
                   new RoutedEventArgs(ColorChangedEvent, e.NewValue));
           }
      
           private static void OnUseDynamicBorderChanged(
               DependencyObject d, DependencyPropertyChangedEventArgs args)
           {
               ColorPicker colorPicker = d as ColorPicker;
               colorPicker = colorPicker ?? throw new ArgumentException();
      
               colorPicker.BorderBrush = (bool)args.NewValue ? new SolidColorBrush(colorPicker.Color) : colorPicker._initializeBorderBrush;
           }
      
           public override void OnApplyTemplate()
           {
               base.OnApplyTemplate();
      
               RangeBase slider = GetTemplateChild(&quot;PART_RedSlider&quot;) as RangeBase;
               if (slider != null)
               {
                   Binding binding = new Binding()
                   {
                       Path = new PropertyPath(&quot;Red&quot;),
                       Source = this,
                       Mode = BindingMode.TwoWay
                   };
                   slider.SetBinding(RangeBase.ValueProperty, binding);
                   slider.Maximum = RGBMaxValue;
               }
      
               slider = GetTemplateChild(&quot;PART_GreenSlider&quot;) as RangeBase;
               if (slider != null)
               {
                   Binding binding = new Binding()
                   {
                       Path = new PropertyPath(nameof(Green)),
                       Source = this,
                       Mode = BindingMode.TwoWay
                   };
                   slider.SetBinding(RangeBase.ValueProperty, binding);
                   slider.Maximum = RGBMaxValue;
               }
      
               slider = GetTemplateChild(&quot;PART_BlueSlider&quot;) as RangeBase;
               if (slider != null)
               {
                   Binding binding = new Binding()
                   {
                       Path = new PropertyPath(nameof(Blue)),
                       Source = this,
                       Mode = BindingMode.TwoWay
                   };
                   slider.SetBinding(RangeBase.ValueProperty, binding);
                   slider.Maximum = RGBMaxValue;
               }
      
               SolidColorBrush brush = GetTemplateChild(&quot;PART_PreviewBrush&quot;) as SolidColorBrush;
               if (brush != null)
               {
                   Binding bd = new Binding
                   {
                       Path = new PropertyPath(nameof(brush.Color)),
                       Source = brush,
                       Mode = BindingMode.OneWayToSource
                   };
                   SetBinding(ColorPicker.ColorProperty, bd);
               }
           }
      
       }
      

      }

    6. 差不多就是这样一个简单的ColorPicker就出来了.另外增加一个UseDynamicBorder,来控制控件边框的颜色是否动态改变.
      看一下效果图

      </div>
  • 相关阅读:
    dsp
    vector.cpp introducing the vector template.
    Bookmarks
    C#多线程参数传递.cs
    vector操作笔记
    Paragma & Bytes
    今天开博
    一台linux服务器挂载另外一台linux服务器文件系统
    nginx基于mysql的身份验证
    Ubuntu下编译nginx
  • 原文地址:https://www.cnblogs.com/Laggage/p/10706376.html
Copyright © 2011-2022 走看看