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。
<ResourceDictionary
xmlns="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