WPF_13_自定义元素

WPF支持样式、内容控件和模板,这些特性提供了多种方式来完善和扩展标准的控件,因此不再强调自定义控件。

  • 样式 - 方便地重用控件属性的组合。甚至可使用触发器应用效果。
  • 内容控件 - 所有继承自 ContentControl 类的控件都支持嵌套的内容。
  • 控件模板 - 所有控件都是无外观的,意味着都具有硬编码的功能,外观是通过控件模板单独定义的。
  • 数据模板 - 所有派生自 ItemsControl 的类都支持数据模板,可创建某些数据对象类型的富列表表示。

因此当希望微调元素的外观时,自定义元素并非最佳选择。如果希望改变底层的功能时,自定义元素就十分有用了。一般在专门的类库程序集(DLL)中放置自定义元素,可在多个程序之间共享自定义元素。

构建自定义控件

创建自定义控件的第一步是选择正确的基类进行继承:

基类说明
FrameworkElement最低级的基类,希望重写 OnRender() 方法
Control最常用的基类,是所有用户交互小组件的基类。Control添加了背景,前景,字体和内容对齐,Tab顺序,鼠标双击,Template属性
ContentControl能够显示任意单一内容的控件的基类
UserControl可使用设计视图进行配置的内容控件
ItemsControl 或 SelectorItemsControl是封装项列表的控件的基类,但不支持选择
Panel具有布局逻辑控件的基类
Decorator封装其他元素的元素的基类
定义依赖项属性
// 1:定义静态字段,以Property结尾
public static DependencyProperty ColorProperty;

// 2:静态的构造函数
static ColorPicker()
{
    // 依赖属性
    ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker),
        new FrameworkPropertyMetadata(Colors.Black, new PropertyChangedCallback(OnColorChanged)));

    // 路由事件
    // RoutedEventHandler委托用于不带额外信息的路由事件
    // RoutedPropertyChangedEventHandler用于提供属性发生之后的旧值和新值的路由事件
    ColorChangedEvent = EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble,
        typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPicker));
}
// 属性变化的回调函数
private static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    // 当 Color 值改变时修改 RGB的值
    Color newColor = (Color)e.NewValue;
    ColorPicker colorPicker = (ColorPicker)sender;
    colorPicker.Red = newColor.R;
    colorPicker.Green = newColor.G;
    colorPicker.Blue = newColor.B;
    // 引发路由事件
    Color oldColor = (Color)e.OldValue;
    RoutedPropertyChangedEventArgs<Color> args = new RoutedPropertyChangedEventArgs<Color>(oldColor, newColor);
    args.RoutedEvent = ColorPicker.ColorChangedEvent;
    colorPicker.RaiseEvent(args);
}

// 3:添加属性封装器,使访问更加容易,并可在XAML中使用它们
public Color Color
{
    get { return (Color)GetValue(ColorProperty); }
    // 当属性变化时 SetValue 引发回调函数
    set { SetValue(ColorProperty, value); }
}

// 4: 路由事件,当发生一些事情时用于通知控件的使用者
public static readonly RoutedEvent ColorChangedEvent;
// 路由事件委托 - 不一定要为事件签名创建新的委托
// RoutedEventHandler委托用于不带额外信息的路由事件
// RoutedPropertyChangedEventHandler用于提供属性发生之后的旧值和新值的路由事件
public event RoutedPropertyChangedEventHandler<Color> ColorChanged
{
    add { AddHandler(ColorChangedEvent, value); }
    remove { RemoveHandler(ColorChangedEvent, value); }
}
命令支持
  • 添加将控件链接到特定命令的命令绑定
  • 为命令创建新的 RoutedUICommand 对象,作为自定义控件的静态字段。
// 第一次创建控件时是创建命令绑定的最佳时机
public ColorPicker()
{
    InitializeComponent();
    SetUpCommands();
}

private void SetUpCommands()
{
    CommandBinding binding = new CommandBinding(ApplicationCommands.Undo, UndoCommand_Executed, UndoCommand_CanExecute);
    this.CommandBindings.Add(binding);
}
private void UndoCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = previousColor.HasValue;
}
private void UndoCommand_Executed(object sender, ExecuteRoutedEventArgs e)
{
    this.Color = (Color)previousColor;
}
<Button Command="Undo" CommandTarget="{Binding ElementName=colorPicker}">
Undo
</Button>

上面代码中的命令比较脆弱,因为可以自由地修改CommandBindings集合。更可靠的技术是使用 CommandManager.RegisterClassCommandBinding 方法在静态构造函数中创建命令。

我的公众号

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值