1.選擇正確的基類進行繼承,比較好的起點是UserControl
一般編譯爲DLL,以方便通用
2.創建依賴項屬性
1.先爲之定義靜態字段 如public static DependencyProperty ColorProperty;,
2.定義靜態構造函數,其中包含註冊依賴項屬性
3.將依賴項屬性封裝爲屬性以便訪問
4.定義回調函數以供修改對應的屬性和依賴項屬性值
3.定義路由事件
1.定義靜態路由事件
2.在靜態構造函數中註冊事件
3.創建.NET事件封裝器來公開事件
4.添加引發該事件的代碼,調用繼承自DependencyObject基類的RaiseEvent()方法
4.添加命令支持
下面是完整代碼:
xaml:
<UserControl x:Class="WpfApp1.ColorPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="colorPicker">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Slider Name="sliderRed" Minimum="0" Maximum="255" Margin="{Binding ElementName=colorPicker,Path=Padding}"
Value="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Path=Red}"/>
<Slider Grid.Row="1" Name="sliderGreed" Minimum="0" Maximum="255" Value="{Binding ElementName=colorPicker,Path=Green}"/>
<Slider Grid.Row="2" Name="sliderBlue" Minimum="0" Maximum="255" Value="{Binding ElementName=colorPicker,Path=Blue}"/>
<Rectangle Grid.Column="1" Grid.RowSpan="3" Width="50" Stroke="Black" StrokeThickness="1">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding ElementName=colorPicker,Path=Color}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</UserControl>
後臺:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace WpfApp1
{
/// <summary>
/// 自定義控件顏色拾取器
/// </summary>
public partial class ColorPicker : UserControl
{
public static DependencyProperty ColorProperty;
public static DependencyProperty RedProperty;
public static DependencyProperty GreenProperty;
public static DependencyProperty BlueProperty;
public static readonly RoutedEvent ColorChangeEvent;
Color? previousColor;
public event RoutedPropertyChangedEventHandler<Color> ColorChanged
{
add { AddHandler(ColorChangeEvent, value); }
remove { RemoveHandler(ColorChangeEvent, value); }
}
public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
public byte Red
{
get { return (byte)GetValue(RedProperty); }
set { SetValue(RedProperty, value); }
}
public byte Green
{
get { return (byte)GetValue(GreenProperty); }
set { SetValue(GreenProperty, value); }
}
public byte Blue
{
get { return (byte)GetValue(BlueProperty); }
set { SetValue(BlueProperty, value); }
}
public ColorPicker() => InitializeComponent();
static ColorPicker()
{
//註冊依賴項屬性
ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker),
new FrameworkPropertyMetadata(Colors.Black, new PropertyChangedCallback(OnColorChanged)));
RedProperty = DependencyProperty.Register("Red", typeof(byte), typeof(ColorPicker),
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));
GreenProperty = DependencyProperty.Register("Green", typeof(byte), typeof(ColorPicker),
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));
BlueProperty = DependencyProperty.Register("Blue", typeof(byte), typeof(ColorPicker),
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));
ColorChangeEvent = EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPicker));
CommandManager.RegisterClassCommandBinding(typeof(ColorPicker),
new CommandBinding(ApplicationCommands.Undo, UndoCommand_Excuted, UndoCommand_CanExecute));
}
static void UndoCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
ColorPicker colorPicker = sender as ColorPicker;
e.CanExecute = colorPicker.previousColor.HasValue;//只要有以前緩存的顏色值就允許執行命令
}
static void UndoCommand_Excuted(object sender, ExecutedRoutedEventArgs e)
{
ColorPicker colorPicker = sender as ColorPicker;
Color currentColor = colorPicker.Color;
colorPicker.Color = (Color)colorPicker.previousColor;
}
static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Color newColor = (Color)e.NewValue;
Color oldColor = (Color)e.OldValue;
ColorPicker colorPicker = sender as ColorPicker;
colorPicker.Red = newColor.R; colorPicker.Green = newColor.G; colorPicker.Blue = newColor.B;
RoutedPropertyChangedEventArgs<Color> args = new RoutedPropertyChangedEventArgs<Color>(oldColor, newColor, ColorChangeEvent);
colorPicker.RaiseEvent(args);
colorPicker.previousColor = (Color)e.OldValue;
}
static void OnColorRGBChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ColorPicker colorPicker = sender as ColorPicker;
Color color = colorPicker.Color;
//修改對應的屬性和依賴項屬性值
if (e.Property == RedProperty) color.R = (byte)e.NewValue;
else if (e.Property == GreenProperty) color.G = (byte)e.NewValue;
else if (e.Property == BlueProperty) color.B = (byte)e.NewValue;
colorPicker.Color = color;
}
}
}
使用:
xaml:
<local:ColorPicker x:Name="colorPicker" ColorChanged="ColorPicker_ColorChanged" Color="Beige" Margin="49,263,573,27"/>
<Button x:Name="button" Content="Undo" HorizontalAlignment="Left" Margin="241,270,0,0" VerticalAlignment="Top" Width="75"
Command="Undo" CommandTarget="{Binding ElementName=colorPicker}"/>
後臺:
void ColorPicker_ColorChanged(object sender, RoutedPropertyChangedEventArgs<Color> e)
{
Console.WriteLine("新顏色是" + e.NewValue.ToString());
}