首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

WPF自定义控件完整流程(4)

在WPF中创建自定义控件的完整流程

1. 选择控件基类

根据功能需求选择合适的基类:

| 基类类型 | 适用场景 | 特点 | |--------------------|-----------------------------------|-----------------------------| | UserControl | 快速组合现有控件 | 设计器支持,不可模板化 | | Control | 需要完全自定义外观和行为的控件 | 支持模板化,高可扩展性 | | ContentControl | 包含单个子元素的容器控件 | 支持内容模型 | | ItemsControl | 展示集合数据的控件 | 支持项模板和面板定制 |

示例代码(继承Control):

public class CustomButton : Control

{

  static CustomButton()

  {

      DefaultStyleKeyProperty.OverrideMetadata(

          typeof(CustomButton),

          new FrameworkPropertyMetadata(typeof(CustomButton)));

  }

}

2. 定义依赖属性

使用依赖属性系统实现数据绑定支持:

public class CustomButton : Control

{

  // 定义按钮角半径属性

  public static readonly DependencyProperty CornerRadiusProperty =

      DependencyProperty.Register(

          name: "CornerRadius",

          propertyType: typeof(CornerRadius),

          ownerType: typeof(CustomButton),

          new FrameworkPropertyMetadata(

              defaultValue: new CornerRadius(4),

              FrameworkPropertyMetadataOptions.AffectsRender));

  // CLR属性包装器

  public CornerRadius CornerRadius

  {

      get => (CornerRadius)GetValue(CornerRadiusProperty);

      set => SetValue(CornerRadiusProperty, value);

  }

}

属性注册参数说明:

name:属性名称

propertyType:属性类型(必须使用可冻结类型)

ownerType:所属控件类型

defaultValue:默认值

metadataOptions:影响渲染/布局的选项

3. 创建控件模板

在Themes/Generic.xaml中定义默认外观:

<ResourceDictionary

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:YourNamespace">

  <Style TargetType="{x:Type local:CustomButton}">

      <Setter Property="Template">

          <Setter.Value>

              <ControlTemplate TargetType="{x:Type local:CustomButton}">

                  <!-- 模板结构 -->

                  <Border x:Name="border"

                          Background="{TemplateBinding Background}"

                          CornerRadius="{TemplateBinding CornerRadius}"

                          BorderBrush="{TemplateBinding BorderBrush}"

                          BorderThickness="{TemplateBinding BorderThickness}">

                      <ContentPresenter

                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"

                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>

                  </Border>

                  <!-- 视觉状态 -->

                  <ControlTemplate.Triggers>

                      <Trigger Property="IsMouseOver" Value="True">

                          <Setter TargetName="border"

                                  Property="Background"

                                  Value="#FFE0E0E0"/>

                      </Trigger>

                  </ControlTemplate.Triggers>

              </ControlTemplate>

          </Setter.Value>

      </Setter>

  </Style>

模板设计要点:

使用TemplateBinding关联控件属性

命名模板部件遵循PART_前缀规范

定义视觉状态触发器实现交互效果

4. 实现控件逻辑

添加交互逻辑和事件处理:

public class CustomButton : Control

{

  // 定义路由事件

  public static readonly RoutedEvent SpecialClickEvent =

      EventManager.RegisterRoutedEvent(

          "SpecialClick",

          RoutingStrategy.Bubble,

          typeof(RoutedEventHandler),

          typeof(CustomButton));

  // 事件包装器

  public event RoutedEventHandler SpecialClick

  {

      add => AddHandler(SpecialClickEvent, value);

      remove => RemoveHandler(SpecialClickEvent, value);

  }

  // 重写鼠标事件

  protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)

  {

      base.OnMouseLeftButtonDown(e);

      RaiseEvent(new RoutedEventArgs(SpecialClickEvent, this));

  }

  // 获取模板部件

  private Border _border;

  public override void OnApplyTemplate()

  {

      base.OnApplyTemplate();

      _border = GetTemplateChild("border") as Border;

      if (_border != null)

      {

          _border.MouseEnter += OnBorderMouseEnter;

      }

  }

}

5. 注册资源字典

确保项目正确识别控件模板:

  <ResourceDictionary>

      <ResourceDictionary.MergedDictionaries>

          <ResourceDictionary Source="/YourAssembly;component/Themes/Generic.xaml"/>

      </ResourceDictionary.MergedDictionaries>

  </ResourceDictionary>

重要验证点:

确认程序集名称与Source路径一致

检查XAML文件的生成操作是否为Page

确保资源字典路径大小写正确

6. 使用自定义控件

在XAML中引用并配置:

<Window

  xmlns:local="clr-namespace:YourNamespace;assembly=YourAssembly">

  <Grid>

      <local:CustomButton

          Content="Click Me"

          CornerRadius="8"

          Background="#FF2196F3"

          BorderThickness="2"

          SpecialClick="CustomButton_SpecialClick"/>

  </Grid>

调试技巧:

使用Snoop工具检查可视化树

在代码中验证模板部件是否成功获取

检查依赖属性绑定是否正确更新

使用PresentationTraceSources.TraceLevel=High调试绑定

高级实现技巧

视觉状态管理

// 定义视觉状态组

VisualStateManager.GoToState(this, "Pressed", true);

// 在模板中添加状态动画

      <VisualState x:Name="Normal"/>

      <VisualState x:Name="Pressed">

          <Storyboard>

                            To="DarkBlue" Duration="0:0:0.2"/>

          </Storyboard>

      </VisualState>

  </VisualStateGroup>

性能优化方案

// 使用DrawingVisual进行复杂渲染

protected override void OnRender(DrawingContext drawingContext)

{

  var geometry = new StreamGeometry();

  using (var context = geometry.Open())

  {

      context.BeginFigure(new Point(0, 0), true, true);

      context.LineTo(new Point(50, 50), true, false);

  }

  geometry.Freeze();

  drawingContext.DrawGeometry(Brushes.Black, null, geometry);

}

支持主题切换

Themes/

├─ Generic.xaml          (默认主题)

├─ DarkTheme.xaml        (深色主题)

└─ HighContrast.xaml     (高对比度主题)

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OfaMKW3cfnmih4mmppOmcupg0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券