WPF创建简单用户控件

基本概念

用户控件(User Control)​​是一种可重用的UI组件,通过组合现有控件来创建自定义功能模块。它本质上是一个容器,可以包含其他控件并封装其交互逻辑。

主要特点

  • ​继承自UserControl类​​
  • ​XAML+代码后置
  • 可重用​​的独立功能单元
  • 可自定义属性、方法和事件​

核心优势

  1. 开发效率提升
  2. 维护性增强
  3. 功能解耦

示例

假设需要封装一个FileSelectorBox控件,用来实现文件选择的功能。

  • 控件组成:
    由一个TextBlock和一个Button组成。
  • 依赖属性:
    FilePath:当前选择的文件路径
  • 自定义事件:
    OnFileChanged:当文件路径发生改变

创建用户控件

右键项目,选择添加,选择用户控件

组合现有控件

1
2
3
4
5
6
7
8
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"/>
<Button Grid.Column="1" Content="选择" Width="71"/>
</Grid>

添加依赖属性和自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public event EventHandler OnFileChanged;

public static readonly DependencyProperty FilePathProperty =
DependencyProperty.Register(
"FilePath", // 属性名称
typeof(string), // 属性类型
typeof(FileSelectorBox), // 所属类型
new PropertyMetadata(null, OnValuesChanged)); // 默认值,添加回调方法

public string FilePath
{
get { return (string)GetValue(FilePathProperty); }
set { SetValue(FilePathProperty, value); OnFileChanged?.Invoke(this, EventArgs.Empty); }
}

private static void OnValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// 回调方法
// 外部修改依赖属性的值时,将在这里回调...
}

当FilePath被修改时,需要修改TextBlock的内容

1
2
<TextBlock Grid.Column="0" Text="{Binding FilePath, 
RelativeSource={RelativeSource AncestorType=UserControl}}" />

按钮功能

当按钮点击时,需要弹出一个文件选择框来选择文件

1
<Button Grid.Column="1" Content="选择" Width="71" Click="Button_Click" /> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
switch(button.Content)
{
case "选择":
OpenFileDialog openFileDialog = new()
{
Title = "选择文件",
Filter = "All File|*.*"
};
openFileDialog.ShowDialog();
FilePath = openFileDialog.FileName;
break;
}
}

使用

1
2
3
<Grid>
<local:FileSelectorBox FilePath="{Binding ExternalFilePath, Mode=TwoWay}" OnFileChanged="FileSelectorBox_OnFileChanged"/>
</Grid>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public partial class ToolMainWindow : UserControl, INotifyPropertyChanged
{
private string _externalFilePath = string.Empty; // 数据源,也可以是自定义的数据模型

public string ExternalFilePath
{
get { return _externalFilePath; }
set { _externalFilePath = value; OnPropertyChanged(nameof(ExternalFilePath)); } // 通知属性值已更改
}

public ToolMainWindow()
{
InitializeComponent();
DataContext = this; // 设置数据上下文
}

public event PropertyChangedEventHandler? PropertyChanged; // 实现接口

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

private void FileSelectorBox_OnFileChanged(object sender, EventArgs e)
{
Growl.Info($"ExternalFilePath发生变化:{ExternalFilePath}");
}
}

资源下载

https://www.taonotespace.com/download/UserControlDemo.zip