1,定义无外观控件。
- 定义默认样式,在其静态构造函数中调用DefaultStyleKeyProperty.OverrideMetadata()。
//设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
- 在项目中创建Themes文件夹, 在Themes文件夹中创建资源字典:generic.xaml。/Themes/generic.xaml 此格式路径为规定格式不得修改,此路径字典中的样式将被自动识别为自定义控件的默认样式。
- 样式必须指定适用的对象类型:TargetType
<Style TargetType="local:ColorPicker"> <!--必须指定类型-->
- 在generic.xaml中合并位于themes/colorpicker.xaml的字典时,需要使用包含程序集的路径(assemblyName;component/themes/colorpicker.xaml),如果只是使用/themes/colorpicker.xaml虽然在运行时可以正常运行,但是在编辑状态下无法预览效果。
2,使用Vs生成无外观控件框架。
- 选择自定义控件
- 自动生成包含静态样式重写的静态构造函数 。
public class ColorPicker : Control{static ColorPicker(){//设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));}}
- 自动创建Themes文件,以及Themes文件下的generic.xaml资源字典。
3,定义资源字典:colorpicker.xaml。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:无外观控件"><Style TargetType="local:ColorPicker"> <!--必须指定类型--><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="local:ColorPicker"><Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"><Grid Margin="{TemplateBinding Padding}"><Grid.RowDefinitions><RowDefinition ></RowDefinition><RowDefinition ></RowDefinition><RowDefinition ></RowDefinition><RowDefinition ></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="auto"></ColumnDefinition><ColumnDefinition Width="3*"></ColumnDefinition><ColumnDefinition Width="2*"></ColumnDefinition></Grid.ColumnDefinitions><Grid.Resources><Style TargetType="TextBlock"><Setter Property="VerticalAlignment" Value="Center"></Setter><Setter Property="Margin" Value="5,0,0,0"></Setter></Style><Style TargetType="Slider"><Setter Property="VerticalAlignment" Value="Center"></Setter><Setter Property="Margin" Value="0,5,5,5"></Setter><Setter Property="Maximum" Value="255"></Setter><Setter Property="Minimum" Value="0"></Setter><Setter Property="SmallChange" Value="1"></Setter></Style></Grid.Resources><TextBlock Text="Alpha:"></TextBlock><Slider x:Name="PART_AlphaSlider" Grid.Column="1"></Slider><TextBlock Text="Red:" Grid.Row="1"></TextBlock><Slider x:Name="PART_RedSlider" Grid.Row="1" Grid.Column="1"></Slider><TextBlock Text="Green:" Grid.Row="2"></TextBlock><Slider x:Name="PART_GreenSlider" Grid.Row="2" Grid.Column="1"></Slider><TextBlock Text="Blue:" Grid.Row="3"></TextBlock><Slider x:Name="PART_BlueSlider" Grid.Row="3" Grid.Column="1"></Slider><Rectangle Grid.Column="2" Grid.RowSpan="4"><Rectangle.Fill><SolidColorBrush x:Name="PART_RecBrush"></SolidColorBrush></Rectangle.Fill></Rectangle></Grid></Border></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>
4,在generic.xaml中添加资源字典colorpicker.xaml。
<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="无外观控件;component/Themes/colorpicker.xaml"></ResourceDictionary><ResourceDictionary Source="无外观控件;component/Themes/FlipPanel.xaml"></ResourceDictionary></ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
5,编写代码
[TemplatePart(Name = "PART_AlphaSlider", Type = typeof(RangeBase))]//此特性无特殊意义,只是用于标识提示[TemplatePart(Name = "PART_RedSlider", Type = typeof(RangeBase))][TemplatePart(Name = "PART_GreenSlider", Type = typeof(RangeBase))][TemplatePart(Name = "PART_BlueSlider", Type = typeof(RangeBase))][TemplatePart(Name = "PART_RecBrush", Type = typeof(SolidColorBrush))]public class ColorPicker : Control{//注册依赖属性public static readonly DependencyProperty AlphaProperty;public static readonly DependencyProperty RedColorProperty;public static readonly DependencyProperty GreenColorProperty;public static readonly DependencyProperty BlueColorProperty;public static readonly DependencyProperty ColorProperty;public static readonly RoutedEvent ColorChangedEvent;static ColorPicker(){//设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));AlphaProperty = DependencyProperty.Register("Alpha", typeof(Byte), typeof(ColorPicker), new PropertyMetadata((byte)0, RedGreenBlueChangedCallBack));RedColorProperty = DependencyProperty.Register("Red", typeof(Byte), typeof(ColorPicker), new PropertyMetadata((byte)0, RedGreenBlueChangedCallBack));GreenColorProperty = DependencyProperty.Register("Green", typeof(Byte), typeof(ColorPicker), new PropertyMetadata((byte)0, RedGreenBlueChangedCallBack));BlueColorProperty = DependencyProperty.Register("Blue", typeof(Byte), typeof(ColorPicker), new PropertyMetadata((byte)0, RedGreenBlueChangedCallBack));ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker), new PropertyMetadata(Colors.Yellow, ColorPropertyChanged));ColorChangedEvent = EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPicker));}public override void OnApplyTemplate(){//进行绑定设置RangeBase alpha = GetTemplateChild("PART_AlphaSlider") as RangeBase;RangeBase red = GetTemplateChild("PART_RedSlider") as RangeBase;RangeBase green = GetTemplateChild("PART_GreenSlider") as RangeBase;RangeBase blue = GetTemplateChild("PART_BlueSlider") as RangeBase;SolidColorBrush brush = GetTemplateChild("PART_RecBrush") as SolidColorBrush;alpha?.SetBinding(Slider.ValueProperty, new Binding(nameof(Alpha)) { Source = this });red?.SetBinding(Slider.ValueProperty, new Binding(nameof(Red)) { Source = this });green?.SetBinding(Slider.ValueProperty, new Binding(nameof(Green)) { Source = this });blue?.SetBinding(Slider.ValueProperty, new Binding(nameof(Blue)) { Source = this });// this.SetBinding(ColorProperty, new Binding("Color") { Source = brush });BindingOperations.SetBinding(brush, SolidColorBrush.ColorProperty, new Binding(nameof(Color)) { Source = this });base.OnApplyTemplate();}private static void ColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){Color curColor = (Color)e.NewValue;ColorPicker picker = d as ColorPicker;picker.Alpha = curColor.A;picker.Red = curColor.R;picker.Green = curColor.G;picker.Blue = curColor.B;RoutedPropertyChangedEventArgs<Color> args = new RoutedPropertyChangedEventArgs<Color>((Color)e.OldValue, (Color)e.NewValue);args.RoutedEvent = ColorChangedEvent;picker.RaiseEvent(args);}private static void RedGreenBlueChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e){ColorPicker picker = d as ColorPicker;Color curColor = picker.Color;byte val = (byte)e.NewValue;switch (e.Property.Name){case "Alpha":curColor.A = val;break;case "Red":curColor.R = val;break;case "Green":curColor.G = val;break;case "Blue":curColor.B = val;break;default:break;}picker.Color = curColor;}/// <summary>/// 设置颜色的Alpha值/// </summary>/// [System.ComponentModel.Bindable(true)][System.ComponentModel.Browsable(true)][Category("颜色设置")]public byte Alpha{get{return (byte)this.GetValue(AlphaProperty);}set{this.SetValue(AlphaProperty, value);}}/// <summary>/// 设置颜色的Red值/// </summary>[Bindable(true), Browsable(true), Category("颜色设置")]public byte Red{get{return (byte)GetValue(RedColorProperty);}set{SetValue(RedColorProperty, value);}}/// <summary>/// 设置颜色的Green值/// </summary>[Bindable(true), Browsable(true), Category("颜色设置")]public byte Green{get{return (byte)GetValue(GreenColorProperty);}set{SetValue(GreenColorProperty, value);}}/// <summary>/// 设置颜色的Blue值/// </summary>[Bindable(true), Browsable(true), Category("颜色设置")]public byte Blue{get{return (byte)GetValue(BlueColorProperty);}set{SetValue(BlueColorProperty, value);}}/// <summary>/// 设置颜色值/// </summary>[Bindable(true), Browsable(true), Category("颜色设置")]public Color Color{get{return (Color)GetValue(ColorProperty);}set{SetValue(ColorProperty, value);}}//对事件进行包装/// <summary>/// 颜色变化完成事件/// </summary>public event RoutedPropertyChangedEventHandler<Color> ColorChanged{add{this.AddHandler(ColorChangedEvent, value);}remove{this.RemoveHandler(ColorChangedEvent, value);}}}
6,在UI中添加此控件。
- 默认情况:
<local:ColorPicker Color="SkyBlue" Padding="5" BorderBrush="Black" BorderThickness="2"></local:ColorPicker>
- 二次自定义控件模板:
<Window.Resources><ControlTemplate x:Key="FancyColorPickerTemplate"><Border Background="LightGoldenrodYellow"BorderBrush="Black"BorderThickness="1"><Grid><Grid.RowDefinitions><RowDefinition></RowDefinition><RowDefinition Height="Auto"></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition></ColumnDefinition><ColumnDefinition Width="Auto"></ColumnDefinition><ColumnDefinition Width="Auto"></ColumnDefinition><ColumnDefinition Width="Auto"></ColumnDefinition></Grid.ColumnDefinitions><Grid.Resources><Style TargetType="{x:Type Slider}"><Setter Property="Orientation" Value="Vertical"></Setter><Setter Property="TickPlacement" Value="TopLeft"></Setter><Setter Property="TickFrequency" Value="10"></Setter><Setter Property="Minimum" Value="0"></Setter><Setter Property="Maximum" Value="255"></Setter><Setter Property="Margin" Value="5"></Setter></Style><Style TargetType="{x:Type TextBlock}"><Setter Property="Margin" Value="3"></Setter><Setter Property="FontSize" Value="10"></Setter></Style></Grid.Resources><Ellipse Grid.Column="0" Grid.RowSpan="2" Margin="10" Height="120" Stroke="LightGray" StrokeThickness="5"><Ellipse.Fill><SolidColorBrush x:Name="PART_RecBrush"></SolidColorBrush></Ellipse.Fill></Ellipse><Slider Name="PART_RedSlider" Grid.Column="1"></Slider><TextBlock Grid.Row="1" Grid.Column="1">RED</TextBlock><Slider Name="PART_GreenSlider" Grid.Column="2"></Slider><TextBlock Grid.Row="1" Grid.Column="2">GREEN</TextBlock><Slider Name="PART_BlueSlider" Grid.Column="3"></Slider><TextBlock Grid.Row="1" Grid.Column="3">BLUE</TextBlock></Grid></Border></ControlTemplate></Window.Resources>
- 引用对象资源
<local:ColorPicker Template="{StaticResource FancyColorPickerTemplate}" Padding="5" Grid.Column="1" Margin="5" BorderBrush="BurlyWood" BorderThickness="2" Color="Red">
7,Demo链接
https://download.csdn.net/download/lingxiao16888/89253829?spm=1001.2014.3001.5501