WPF 入门教程(一)

2026-05-16 00:58 230 阅读

一.wpf入门

1.wpf 简介

WPF(Windows Presentation Foundation)是微软推出的基于Windows的用户界面框架,属于.NET Framework 3.0及更高版本的一部分。它提供了统一的编程模型、语言和框架,实现了界面设计人员与开发人员的分离工作。

核心特点

1.​​XAML基础​​:使用可扩展应用程序标记语言(XAML)定义用户界面,实现界面与逻辑代码的分离。 2.​​矢量图形支持​​:提供强大的2D/3D图形渲染能力,基于DirectX技术,支持GPU硬件加速。 3.​​分辨率无关​​:自动识别显示器分辨率并进行缩放,适应不同显示设备。 4.​​数据绑定​​:内置强大的数据绑定机制,支持MVVM模式开发。 5.​​丰富的媒体支持​​:集成文档、音频、视频和动画功能。 技术架构

WPF采用基于DirectX的渲染引擎,相比传统的GDI/GDI+技术,提供了更先进的图形处理能力。

开发优势

设计开发分离​​:设计师可使用Expression Blend等工具设计界面,开发人员专注于业务逻辑。

​​现代化UI​​:支持创建媲美Mac程序的视觉效果,如Vista的半透明窗体效果。

​​跨版本兼容​​:支持从Windows XP到最新Windows系统的运行。

​​多语言支持​​:可使用C#、VB.NET等.NET语言进行开发。

2.与winform对比

1).基础架构差异

​技术基础:

  • WinForms基于GDI+进行软件渲染,采用传统的Windows消息循环机制。
  • WPF基于DirectX进行硬件加速渲染,使用XAML声明式UI设计

​设计理念:

  • WinForms采用事件驱动模型,强调快速开发
  • WPF采用数据驱动模型,支持MVVM模式

2).功能特性对比

特性 WinForms WPF
UI设计​​ 拖拽控件,像素级布局 XAML声明式设计,矢量布局
​​图形能力​​ 基本2D图形 支持2D/3D、动画、特效
​​数据绑定​​ 简单绑定,需手动更新 强大双向绑定,自动更新
分辨率适配​​ 固定DPI 自动高DPI适配
学习曲线​​ 简单易上手 较陡峭(XAML+MVVM)

3).性能表现

启动速度:

  • WinForms启动更快(依赖项少)

  • WPF启动较慢(需加载XAML解析器等) ​运行时性能:

  • WinForms:简单UI性能好,复杂图形性能下降

  • WPF:复杂图形性能优异(硬件加速),简单UI可能有开销

内存占用​​:

  • WinForms内存占用较低
  • WPF内存占用较高(维护更多UI状态)

3.wpf项目结构介绍

3.1 核心文件结构

  • App.xaml和App.xaml.cs:应用程序入口点,定义全局资源和启动设置,App.xaml.cs包含应用程序启动逻辑和生命周期事件处理。
  • MainWindow.xaml和MainWindow.xaml.cs:主窗口的界面布局定义文件(XAML),对应的代码隐藏文件处理窗口逻辑
  • ​Properties文件夹:包含AssemblyInfo.cs(程序集元数据),资源文件(Resources.resx)和设置文件(Settings.settings)。

3.2 常见目录结构

  • 资源管理(Resources):存储图片、字体、样式等资源,可细分为Images、Styles、Themes等子目录
  • 视图组织(Views):存放应用程序页面(XAML文件)
  • 代码分层:数据模型类(Models),MVVM模式中的视图模型(ViewModels),业务逻辑和服务类(Services)
  • 用户控件:自定义控件(Controls)/自定义用户控件(UserControls):存放可重用的自定义控件

3.3 生成目录

  • bin目录:包含Debug和Release版本的生成输出
  • obj目录:包含Debug和Release,存储中间编译结果

3.4 配置文件

  • ​App.config:应用程序配置文件,包含连接字符串等设置
  • .csproj:XML格式的项目配置文件,定义项目属性、引用和构建规则

3.5 项目结构示例

4.App.xaml介绍

App.xaml是WPF(Windows Presentation Foundation)应用程序的核心文件,作为应用程序的主入口点和资源管理中心。

基本概念

  • ​应用程序入口​​:App.xaml是WPF应用程序的启动文件,自动加载并解析

  • ​​代码分离​​:通常与App.xaml.cs配对使用,后者包含应用程序逻辑代码

  • ​​全局资源管理​​:集中管理应用程序级别的资源,如样式、模板和动画 主要功能

  • 资源定义:定义全局样式、模板和数据模板,资源可在整个应用程序中重复使用。

  • 应用程序配置​​:通过StartupUri属性指定启动窗口,配置应用程序初始设置,如窗口大小、标题等。

  • 生命周期管理​​:处理应用程序级别事件(启动、退出、异常等),包含OnStartup、OnExit等重写方法

代码结构示例

StartupUri默认值应该为MainWindow.xaml,由于这里移动了MainWindow.xaml到views文件夹下,所以进行了修改

<Application x:Class="TestWpfApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:TestWpfApp"
             StartupUri="./views/MainWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>



using System.Windows;

namespace TestWpfApp
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            // 启动逻辑
        }
    }
}

5.Application生命周期

WPF应用程序的生命周期由Application类控制,主要包括启动、运行和关闭三个阶段。

5.1 启动阶段

5.1.1 程序入口

  • WPF应用程序从App.xaml文件开始执行,自动生成Main()方法作为程序入口。
  • 创建Application实例并初始化。

5.1.2 ​初始化过程​​

  • 加载App.xaml文件中的配置和资源
  • 调用InitializeComponent()方法初始化XAML
  • 触发Startup事件(通过OnStartup方法)

5.1.3 主窗口创建​​

  • 根据StartupUri属性创建并显示主窗口
  • 或可在OnStartup方法中手动创建窗口

5.2 运行阶段

5.2.1 消息循环

  • 调用Application.Run()方法进入消息循环
  • 应用程序开始处理用户输入和事件

5.2.2 状态变化​​

  • Activated​​:当应用程序窗口获得焦点时触发
  • ​​Deactivated​​:当应用程序窗口失去焦点时触发

5.2.3 异常处理​​

  • DispatcherUnhandledException:处理UI线程未捕获的异常
  • AppDomain.CurrentDomain.UnhandledException:处理所有线程的未捕获异常
  • TaskScheduler.UnobservedTaskException:处理Task异常

5.3 关闭阶段

5.3.1 ​关闭模式

  • OnLastWindowClose:最后一个窗口关闭时退出(默认)
  • OnMainWindowClose:主窗口关闭时退出
  • OnExplicitShutdown:必须显式调用Shutdown()方法退出

​5.3.2 关闭事件

  • 触发Exit事件(通过OnExit方法)
  • 执行资源清理操作

5.3.3 关闭方法

  • Application.Current.Shutdown():优雅关闭
  • Environment.Exit(0):强制立即终止

5.4 关键事件顺序

Startup → Activated → (运行期间可能多次触发Activated/Deactivated) → Exit

using System;
using System.Windows;

namespace TestWpfApp
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        // 启动
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            Console.WriteLine("启动");
        }

        // 获取焦点
        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            Console.WriteLine("获取焦点");
        }

        // 失去焦点
        protected override void OnDeactivated(EventArgs e)
        {
            base.OnDeactivated(e);
            Console.WriteLine("失去焦点");
        }

        // 关闭
        protected override void OnExit(ExitEventArgs e)
        {
            base.OnExit(e);
            Console.WriteLine("关闭");
        }
    }
}

6.窗体生命周期

6.1 主要生命周期阶段

6.1.1 ​​​​创建与初始化

1.构造函数调用:通过new Window()实例化窗口对象 2.InitializeComponent():解析XAML并构建可视化树 3.OnInitialized事件:元素初始化完成,数据绑定已准备

6.1.2 加载阶段

1.SourceInitialized:窗口句柄(HWND)已创建,可进行Win32 API调用 2.Loaded事件:窗口布局完成,所有子控件已加载 3.ContentRendered:窗口内容首次完成渲染

6.1.3 激活/停用

1.Activated:窗口获得焦点(首次显示或用户切换回来) 2.Deactivated:窗口失去焦点(用户切换到其他窗口)

6.1.4 关闭阶段

1.Closing:窗口即将关闭,可取消关闭操作(e.Cancel = true) 2.Closed:窗口已关闭,可进行资源清理 3.Unloaded:窗口从可视化树中移除

6.2 关键事件顺序

构造函数 → OnInitialized → SourceInitialized → Loaded → ContentRendered → Activated → (运行时可能多次Activated/Deactivated) → Closing → Closed → Unloaded

6.3 窗口点击关闭时拦截

using System.ComponentModel;
using System.Windows;

namespace TestWpfApp
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            e.Cancel = MessageBox.Show("确定要关闭吗?", "提示", MessageBoxButton.YesNo) != MessageBoxResult.Yes;
        }
    }
}

7.窗体结构介绍

7.1 基本组成结构

7.1.1 ​客户区与非客户区

  • 非客户区​​:包括边框(Border)、标题栏(Title Bar)、图标(Icon)、最大化/最小化/关闭按钮等系统标准元素
  • ​​客户区​​:开发者自定义内容的工作区域,可放置各种WPF控件

7.1.2 ​​核心类继承​​

System.Object
↓
System.Windows.Threading.DispatcherObject
↓
System.Windows.DependencyObject
↓
System.Windows.Media.Visual
↓
System.Windows.UIElement
↓
System.Windows.FrameworkElement
↓
System.Windows.Controls.Control
↓
System.Windows.Window

7.2 XAML文件结构

典型窗体XAML文件包含以下关键元素

<Window x:Class="TestWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        
    </Grid>
</Window>

7.3 后台代码结构

对应XAML的后台代码文件

using System.ComponentModel;
using System.Windows;

namespace TestWpfApp
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

7.4 窗体创建方式

7.4.1 ​​设计时创建

通过Visual Studio添加新项→WPF窗口

7.4.2 运行时创建

// 非模态窗口
var window = new Window1();
window.Show();

// 模态窗口,必须关闭才能回到前一个窗口运行
var dialog = new DialogWindow();
dialog.ShowDialog();

8.窗体常用属性

8.1 外观属性

8.1.1 Title

窗口标题栏显示的文本

8.1.2 Icon

窗口左上角显示的图标

8.1.3 WindowStyle

窗口边框样式,有4种取值

  • None:无边框
  • SingleBorderWindow:单边框(默认)
  • ThreeDBorderWindow:3D边框
  • ToolWindow:工具窗口样式

8.1.4 Background

窗口背景颜色或图像

8.1.5 AllowsTransparency

是否允许透明效果(需配合WindowStyle=None)

8.1.6 Opacity

窗口透明度(0.0-1.0)

8.2 大小与位置属性

8.2.1 Width/Height

窗口的宽度和高度

8.2.2 MinWidth/MinHeight​​

窗口的最小宽度和高度

8.2.3 MaxWidth/MaxHeight​​

窗口的最大宽度和高度

8.2.4 SizeToContent

窗口如何根据内容自动调整大小

  • Manual:手动(默认)
  • Width:宽度自适应
  • Height:高度自适应
  • WidthAndHeight:宽高都自适应

8.2.5 WindowStartupLocation

窗口初始位置

  • Manual:手动指定(通过Left/Top属性)
  • CenterScreen:屏幕中央
  • CenterOwner:父窗口中央

8.2.6 Left/Top

窗口左上角的屏幕坐标

8.3 行为属性

8.3.1 ResizeMode

窗口大小调整模式

  • oResize:不可调整
  • CanMinimize:仅可最小化
  • CanResize:可调整(默认)
  • CanResizeWithGrip:可调整并显示调整手柄

8.3.2 WindowState

窗口初始状态

  • Normal:正常
  • Minimized:最小化
  • Maximized:最大化

8.3.3 Topmost

是否置顶显示

8.3.4 ShowInTaskbar

是否在任务栏显示

8.3.5 ShowActivated

首次显示时是否自动激活

8.4 内容与交互属性

8.4.1 FontFamily/FontSize

窗口默认字体设置

8.4.2 Cursor

窗口默认光标样式

8.4.3 IsEnabled

窗口是否可用

8.4.4 IsHitTestVisible

是否响应鼠标事件

9.程序退出的几种方式



9.1 优雅关闭方式

WPF推荐的关闭方式,会触发Application的Shutdown事件,允许执行清理工作

Application.Current.Shutdown();

9.2 窗口关闭方式

关闭当前窗口,默认当所有窗口关闭后程序退出,实际是否退出程序取决于ShutdownMode设置

this.Close();

9.3 强制退出方式

立即终止进程,不会触发任何关闭事件,强制退出

Environment.Exit(0); // 0表示正常退出

最暴力的退出方式,类似任务管理器结束进程

Process.GetCurrentProcess().Kill();

9.4 关闭模式控制

// 在App.xaml中设置
Application.Current.ShutdownMode = ShutdownMode.OnLastWindowClose; // 默认,最后一个窗体关闭后退出程序
// 或
Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose; // 主窗体关闭后退出程序
//或
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown; // 这需要显式 Shutdown 方法调用来停止应用程序。 否则,应用程序将继续在后台运行。

10.命名空间

10.1 基本命名空间

10.1.1 WPF核心命名空间

默认命名空间,包含所有WPF内置控件(如Button、Grid等)

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

10.1.2 XAML语言命名空间

提供XAML特有功能(如x:Name、x:Class、x:Key等)

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

10.2 自定义命名空间

10.2.1 引用系统类库

xmlns:s="clr-namespace:System;assembly=mscorlib"

10.2.2 引用本地程序集

xmlns:local="clr-namespace:MyApp.Namespace"

10.2.3 引用外部程序集

需要指定程序集名称

xmlns:ext="clr-namespace:External.Namespace;assembly=ExternalLib"

10.3 关键作用

避免命名冲突,通过前缀区分同名类(如local:Button vs x:Button)

二.wpf控件继承树

1.继承树图示

2.介绍

2.1 DispatcherObject

DispatcherObject 是 WPF 中的一个基础类,它为 WPF 对象提供了线程关联性(thread affinity)支持,确保对象只能在创建它的线程(通常是 UI 线程)上被访问。

2.1.1 主要成员

public class DispatcherObject
{
    // 获取与此对象关联的 Dispatcher
    public Dispatcher Dispatcher { get; }
    
    // 检查当前线程是否可以访问此对象
    public bool CheckAccess();
    
    // 验证当前线程是否可以访问此对象,如果不行则抛出异常
    public void VerifyAccess();
}

2.1.2 使用场景

验证线程访问权限​

if (!someControl.CheckAccess())
{
    // 当前线程不是创建控件的线程
    someControl.Dispatcher.Invoke(() => {
        // 在正确的线程上执行操作
        someControl.Content = "Updated";
    });
}
else
{
    // 可以直接访问
    someControl.Content = "Updated";
}

从后台线程更新UI​

// 后台线程中,同步UI线程更新
Application.Current.Dispatcher.Invoke(() => {
    // 这段代码会在UI线程上执行
    textBox.Text = "Updated from background thread";
});

// 后台线程中,异步UI线程更新
Application.Current.Dispatcher.InvokeAsync(() => {
    // 这段代码会在UI线程上执行
    textBox.Text = "Async updated from background thread";
});



2.2 DependencyObject

DependencyObject 是 WPF 的核心基类之一,它为 WPF 属性系统提供了基础支持,实现了依赖属性(Dependency Properties)和附加属性(Attached Properties)的核心功能。

2.2.1 基本概念

​​依赖属性系统:

  • 提供属性值继承、数据绑定、动画和样式支持
  • 比传统 CLR 属性更强大但更复杂

2.2.2 核心功能

依赖属性支持:

public class MyControl : DependencyObject
{
    // 注册依赖属性
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register(
            "MyProperty",
            typeof(string),
            typeof(MyControl),
            new PropertyMetadata("默认值"));
    
    // CLR包装器
    public string MyProperty
    {
        get { return (string)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }
}

附加属性支持:

public static class MyAttachedProperties
{
    public static readonly DependencyProperty IsSpecialProperty =
        DependencyProperty.RegisterAttached(
            "IsSpecial",
            typeof(bool),
            typeof(MyAttachedProperties),
            new PropertyMetadata(false));
    
    public static bool GetIsSpecial(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsSpecialProperty);
    }
    
    public static void SetIsSpecial(DependencyObject obj, bool value)
    {
        obj.SetValue(IsSpecialProperty, value);
    }
}

2.2.3 关键方法

方法 描述
GetValue(DependencyProperty) 获取依赖属性的值
SetValue(DependencyProperty, object) 设置依赖属性的值
ClearValue(DependencyProperty) 清除本地设置的值,恢复默认值
CoerceValue(DependencyProperty) 强制重新计算属性值
SetCurrentValue(DependencyProperty, object) 设置属性值但不改变其绑定

2.2.4 属性值优先级

1.动画值(最高优先级) 2.本地值(通过SetValue设置) 3.模板属性 4.样式触发器 5.样式Setter 6.主题样式 7.继承值 8.默认值(最低优先级)

2.2.5 实际应用示例

自定义控件中使用依赖属性:

public class CustomButton : Button
{
    public static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.Register(
            "CornerRadius",
            typeof(CornerRadius),
            typeof(CustomButton),
            new PropertyMetadata(new CornerRadius(0)));
    
    public CornerRadius CornerRadius
    {
        get { return (CornerRadius)GetValue(CornerRadiusProperty); }
        set { SetValue(CornerRadiusProperty, value); }
    }
}

使用附加属性扩展功能:

// 在XAML中使用
<Button local:MyAttachedProperties.IsSpecial="True" Content="特殊按钮"/>

属性值变更通知:

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register(
        "Value",
        typeof(double),
        typeof(RangeControl),
        new FrameworkPropertyMetadata(
            0.0,
            FrameworkPropertyMetadataOptions.AffectsRender,
            OnValueChanged));

private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (RangeControl)d;
    control.UpdateVisualState();
}



2.3 Visual

Visual 类是 WPF 可视化系统的核心基类,位于 System.Windows.Media 命名空间,为所有可视化元素提供基础渲染支持。

2.3.1 基本概念

在可视化树中的角色​​:

  • Visual 是 WPF 可视化树的构建块
  • 介于 DependencyObject 和 UIElement 之间
  • 提供基础的渲染、变换和命中测试功能

与 FrameworkElement 的关系​​:

  • Visual 是轻量级的渲染基类
  • UIElement 继承自 Visual 并添加了布局、输入和事件系统
  • FrameworkElement 进一步扩展了 UIElement

2.3.2 核心功能

可视化树操作:

// 获取可视化子元素数量
int childCount = VisualTreeHelper.GetChildrenCount(visual);

// 遍历可视化子元素
for (int i = 0; i < childCount; i++)
{
    Visual child = VisualTreeHelper.GetChild(visual, i) as Visual;
    // 处理子元素...
}

命中测试(Hit Testing):

// 简单命中测试
bool isHit = VisualTreeHelper.HitTest(visual, point) != null;

// 高级命中测试回调
HitTestResultBehavior HitTestCallback(HitTestResult result)
{
    // 处理命中结果
    return HitTestResultBehavior.Continue;
}

VisualTreeHelper.HitTest(
    visual, 
    null, 
    HitTestCallback, 
    new PointHitTestParameters(point));

变换支持:

// 应用变换
visual.Transform = new RotateTransform(45);

// 获取相对于其他visual的变换
GeneralTransform transform = visual.TransformToVisual(otherVisual);
Point transformedPoint = transform.Transform(new Point(0, 0));

2.3.3 关键成员

成员 描述
VisualTransform 获取或设置变换
VisualOpacity 获取或设置不透明度
VisualClip 获取或设置裁剪区域
VisualEffect 获取或设置位图效果
VisualParent 获取父Visual
VisualChildrenCount 获取子Visual数量

2.3.4 实际应用场景

自定义渲染

public class CustomVisual : Visual
{
    public CustomVisual()
    {
        // 必须使用DrawingVisual进行自定义渲染
        var drawingVisual = new DrawingVisual();
        using (DrawingContext dc = drawingVisual.RenderOpen())
        {
            dc.DrawRectangle(Brushes.Blue, null, new Rect(0, 0, 100, 100));
        }
        
        // 添加到可视化树
        this.AddVisualChild(drawingVisual);
    }
    
    // 必须重写这些成员
    protected override int VisualChildrenCount => 1;
    protected override Visual GetVisualChild(int index) => /* 返回子Visual */;
}



2.4 UIElement

UIElement 是 WPF 中构建交互式用户界面的核心基类

  • 提供基础输入事件系统
  • 实现布局测量和排列的初步结构
  • 处理焦点和路由事件
  • 支持基本的变换和动画

2.4.1 冒泡事件(Bubbling Events)​

工作原理:事件从触发源(如按钮点击)开始,​​向上​​冒泡到父级控件,直到根元素(如Window)。

示例:Button.Click事件触发后,依次经过StackPanel → Grid → Window

特点:1.命名无前缀(如MouseDown);2.父控件可统一处理子控件事件(如在Grid中处理所有按钮点击);

​中断冒泡:在事件处理中设置e.Handled = true可停止传播。

2.4.2 隧道事件(Tunneling Events)

工作原理​​:事件从根元素​​向下​​隧道传递到触发源,通常用于“预览”或拦截事件

​示例​​:PreviewMouseDown从Window开始,经Grid → StackPanel → Button

特点:命名以Preview前缀(如PreviewKeyDown);允许父控件在事件到达目标前处理或拦截(如禁用特定键盘输入);

中断隧道​​:在父级事件中设置e.Handled = true可阻止事件到达子控件;

2.5 FrameworkElement

扩展布局属性(Width、Margin)、数据绑定(DataContext)和资源管理。

2.5.1 核心属性

布局属性

属性 说明
Margin 元素外边距
HorizontalAlignment 水平对齐方式
VerticalAlignment 垂直对齐方式
Width/Height 显式尺寸设置
MinWidth/MaxWidth 最小/最大宽度
MinHeight/MaxHeight 最小/最大高度

外观属性

属性 说明
Style 样式设置
Template 控件模板
Resources 本地资源字典
DataContext 数据上下文

行为属性

|属性 |说明| |-|-| |IsEnabled| 是否启用| |Visibility |可见性控制| |Focusable |能否获取焦点| |ToolTip |工具提示内容| 

三.布局控件

1.Panel 布局基类

Panel 是 WPF 中所有布局面板的基类,它定义了容器控件如何排列其子元素的基本行为。

1.1 核心功能

1.子元素集合管理:Panel 维护一个子元素集合 (UIElementCollection) 2.布局系统参与:Panel 参与 WPF 的测量(Measure)和排列(Arrange)过程 3.可视化容器:为子元素提供可视化的容器和呈现表面

1.2 主要成员

属性

属性 类型 说明
Children UIElementCollection 获取面板的子元素集合
Background Brush 获取或设置面板的背景画笔
IsItemsHost bool 指示此面板是否为 ItemsControl 生成的项的容器
InternalChildren UIElementCollection 获取子元素的内部集合(供派生类使用)

方法

方法 说明
MeasureOverride(Size) 测量面板及其子元素所需的大小
ArrangeOverride(Size) 排列面板的子元素并确定其最终大小
OnRender(DrawingContext) 参与呈现操作
CreateUIElementCollection(FrameworkElement) 创建新的 UIElementCollection

1.3 布局过程

1.3.1 测量阶段(Measure)

确定子元素所需的大小

  • 调用 MeasureOverride 方法
  • 面板询问每个子元素它们希望有多大

1.3.2 排列阶段(Arrange)

确定子元素的最终位置和大小

  • 调用 ArrangeOverride 方法
  • 面板根据测量结果安排子元素的实际位置

1.4 常用派生类

1.Canvas:绝对定位面板 2.StackPanel:线性堆叠面板 3.WrapPanel:自动换行面板 4.DockPanel:停靠面板 5.Grid:表格布局面板 6.UniformGrid:均匀网格面板

Border有类似于布局控件的功能,但不属于布局控件,并不继承于Panel

2.Grid网格

Grid 是一个二维布局系统,由行和列组成,可以精确控制子元素的位置和大小,提供了类似 HTML 表格的灵活布局方式。

2.1 核心特性

1.行列定义:可以定义任意数量的行和列 2.单元格定位:子元素可以放置在特定的单元格中 3.跨行跨列:子元素可以跨越多个行或列 4.尺寸控制:支持多种尺寸定义方式(固定、自动、比例)

2.2 基本用法

<Grid>
    <!-- 列定义 -->
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="2*"/>
    </Grid.ColumnDefinitions>
    
    <!-- 行定义 -->
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="50"/>
    </Grid.RowDefinitions>
    
    <!-- 子元素 -->
    <Button Grid.Column="0" Grid.Row="0" Content="按钮1"/>
    <Button Grid.Column="1" Grid.Row="1" Content="按钮2"/>
    <Button Grid.Column="2" Grid.Row="2" Grid.ColumnSpan="2" Content="跨列按钮"/>
</Grid>

2.3 尺寸定义类型

类型 语法 说明
固定值 Width="100" 固定像素值
自动 Width="Auto" 根据内容自动调整
比例 Width="*" 按比例分配剩余空间
加权比例 Width="2*" 权重为2的比例分配

2.4 跨行跨列

<Button Grid.Column="1" Grid.Row="1" 
        Grid.ColumnSpan="2" Grid.RowSpan="2"
        Content="跨2列2行的按钮"/>

2.5 行列分隔线

<Grid ShowGridLines="True">
    <!-- 行列定义 -->
</Grid>

注意:ShowGridLines 仅用于调试,实际应用中应使用 Border 或样式实现分隔线效果

3.均分布局UniformGrid

UniformGrid(均匀网格)是 WPF 中一个特殊的布局面板,它提供了一种简单的方式来创建所有单元格大小相同的网格布局。

3.1 核心特点

1.均匀分布:所有单元格具有相同的大小 2.自动排列:子元素按照行或列的顺序自动填充 3.简化定义:无需单独定义行和列 4.固定行列:可以指定固定的行数或列数 

3.2 基本用法

最简单的 UniformGrid

<UniformGrid>
    <Button Content="1"/>
    <Button Content="2"/>
    <Button Content="3"/>
    <Button Content="4"/>
    <Button Content="5"/>
    <Button Content="6"/>
</UniformGrid>

主要属性

属性 类型 说明 默认值
Rows int 设置固定的行数 0 (自动计算)
Columns int 设置固定的列数 0 (自动计算)
FirstColumn int 第一行起始列索引 0
IsItemsHost bool 是否作为 ItemsControl 的项容器 false

3.3 高级用法

固定行列数

<!-- 固定3列,行数自动计算 -->
<UniformGrid Columns="3">
    <Button Content="1"/>
    <Button Content="2"/>
    <!-- 共9个按钮 -->
    <Button Content="9"/>
</UniformGrid>

从指定列开始

<!-- 共5个按钮,从第2列开始排列 -->
<UniformGrid Columns="3" FirstColumn="1">
    <Button Content="1"/>
    <Button Content="2"/>
    <Button Content="3"/>
    <Button Content="4"/>
    <Button Content="5"/>
</UniformGrid>

3.4 与 Grid 的比较

特性 UniformGrid Grid
单元格大小 统一 可不同
行列定义 自动或简单指定 需明确定义
布局复杂度 简单 复杂
适用场景 简单均匀布局 复杂精确布局
性能 较高 较低

4.堆积面板StackPanel

以线性方式(水平或垂直)排列其子元素

4.1 特点

1.线性布局:子元素按单一方向(水平或垂直)依次排列 2.自动堆叠:无需指定位置,自动按顺序排列 3.尺寸控制:可以控制子元素的拉伸方式 4.简单高效:布局计算简单,性能较好

4.2 基本用法

4.2.1 垂直堆叠(默认)

<StackPanel>
    <Button Content="按钮1"/>
    <Button Content="按钮2"/>
    <Button Content="按钮3"/>
</StackPanel>

4.2.2 水平堆叠


<StackPanel Orientation="Horizontal">
    <Button Content="按钮1"/>
    <Button Content="按钮2"/>
    <Button Content="按钮3"/>
</StackPanel>

4.3 主要属性

属性 类型 说明 默认值
Orientation Orientation 排列方向(Vertical/Horizontal) Vertical
Margin Thickness 面板外边距 0
Spacing (WPF 4.0+) double 子元素之间的间距 0

4.4 高级用法

4.4.1 子元素对齐控制

<StackPanel>
    <!-- 水平方向左对齐 -->
    <Button Content="左" HorizontalAlignment="Left" Width="100"/>
    <!-- 水平方向居中 -->
    <Button Content="中" HorizontalAlignment="Center" Width="100"/>
    <!-- 水平方向拉伸 -->
    <Button Content="拉伸" HorizontalAlignment="Stretch"/>
</StackPanel>

4.4.2 滚动支持

<ScrollViewer>
    <StackPanel>
        <!-- 多个子元素 -->
        <Button Content="Item 1" Height="50"/>
        <!-- ... -->
        <Button Content="Item 20" Height="50"/>
    </StackPanel>
</ScrollViewer>

4.5 布局行为

4.5.1 测量阶段

  • 垂直 StackPanel:宽度取最宽子元素,高度为所有子元素高度之和
  • 水平 StackPanel:高度取最高子元素,宽度为所有子元素宽度之和

4.5.2 排列阶段

  • 按指定方向依次排列子元素
  • 考虑子元素的 Margin 和 Alignment 设置

4.5.3 尺寸分配

  • 子元素默认获得其所需尺寸
  • 当空间不足时,按比例压缩(基于 DesiredSize)

4.6 简单的工具栏

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" Background="LightGray">
        <Button Content="新建" Margin="5"/>
        <Button Content="打开" Margin="5"/>
        <Button Content="保存" Margin="5"/>
        
        <!--分割-->
        <Separator Margin="5" Width="2" Background="White"/>
        <Button Content="剪切" Margin="5"/>
        <Button Content="复制" Margin="5"/>
        <Button Content="粘贴" Margin="5"/>
    </StackPanel>
</Grid>

5.换行面板WrapPanel

WrapPanel(换行面板)是 WPF 中一个灵活的布局容器,它能够按照指定方向排列子元素,并在空间不足时自动换行或换列。

5.1 特点

1.自动换行:当空间不足时自动换行/换列 2.方向可控:支持水平和垂直两种排列方向 3.流式布局:类似网页中的流式布局效果 4.均匀排列:默认情况下子元素均匀分布

5.2 基本用法

水平排列(默认)

<WrapPanel>
    <Button Content="按钮1" Width="100"/>
    <Button Content="按钮2" Width="100"/>
    <!-- 更多按钮 -->
    <Button Content="按钮8" Width="100"/>
</WrapPanel>

垂直排列

<WrapPanel Orientation="Vertical">
    <Button Content="按钮1" Height="40"/>
    <Button Content="按钮2" Height="40"/>
    <!-- 更多按钮 -->
    <Button Content="按钮8" Height="40"/>
</WrapPanel>

5.3 主要属性

属性 类型 说明 默认值
Orientation Orientation 排列方向(Horizontal/Vertical) Horizontal
ItemWidth double 统一设置所有子项宽度 NaN (自动)
ItemHeight double 统一设置所有子项高度 NaN (自动)
FlowDirection FlowDirection 内容流动方向(LeftToRight/RightToLeft) LeftToRight

5.4 统一子项尺寸

<WrapPanel ItemWidth="120" ItemHeight="60">
    <Button Content="按钮1"/>
    <Button Content="按钮2"/>
    <!-- 所有按钮将统一为120x60尺寸 -->
</WrapPanel>

5.5 从右向左排列

<WrapPanel FlowDirection="RightToLeft">
    <Button Content="1"/>
    <Button Content="2"/>
    <!-- 元素将从右向左排列 -->
</WrapPanel>

5.6 与滚动视图结合

<ScrollViewer HorizontalScrollBarVisibility="Auto">
    <WrapPanel Width="500">
        <!-- 多个子元素 -->
    </WrapPanel>
</ScrollViewer>

6.停靠面板DockPanel

6.1 核心特点

1.边缘停靠:子元素可以停靠在上、下、左、右四个边缘 2.填充剩余:最后一个子元素可以填充剩余空间 3.动态调整:当面板大小改变时自动调整布局 4.嵌套支持:可以嵌套使用创建复杂布局

6.2 主要属性

属性 类型 说明 默认值
LastChildFill bool 最后一个子元素是否填充剩余空间 True
DockPanel.Dock Dock 子元素的停靠位置(附加属性,Left Top Right Bottom -

6.3 简单使用

<Window x:Class="TestWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel>
        <Grid DockPanel.Dock="Top" Height="60" Background="#ccc"></Grid>
        <Grid DockPanel.Dock="Bottom" Height="100" Background="#c1c1c1"></Grid>
        <Grid DockPanel.Dock="Left" Width="100" Background="#ddd"></Grid>
        <Grid DockPanel.Dock="Right" Width="100" Background="#ddd"></Grid>
        <Grid></Grid>
    </DockPanel>
</Window>

7.画布Canvas

一种采用绝对定位的方式来排列子元素的布局控件,常配合图形控件使用。

7.1 核心特性

1.绝对定位:子元素通过明确的坐标位置放置 2.自由重叠:元素可以自由重叠,通过Z轴控制层次 3.无自动布局:不会自动调整子元素位置或大小 4.高性能:布局计算简单,性能较高

7.2 基本用法

<Window x:Class="TestWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestWpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas>
        <Button Width="180" Height="180" Background="Red" Canvas.Left="20" Canvas.Top="20" Panel.ZIndex="5"/>
        <Button Width="180" Height="180" Background="Blue" Canvas.Left="50" Canvas.Top="50"/>
        <Button Width="180" Height="180" Background="Yellow" Canvas.Left="80" Canvas.Top="80"/>
        <Button Width="180" Height="180" Background="Green" Canvas.Bottom="80" Canvas.Right="80"/>
    </Canvas>
</Window>

7.3 定位属性

附加属性 说明 示例
Canvas.Left 元素左边缘与Canvas左边缘的距离 Canvas.Left="50"
Canvas.Top 元素顶部与Canvas顶部的距离 Canvas.Top="30"
Canvas.Right 元素右边缘与Canvas右边缘的距离 Canvas.Right="20"
Canvas.Bottom 元素底部与Canvas底部的距离 Canvas.Bottom="40"
Canvas.ZIndex 控制元素的Z轴顺序(重叠顺序) Canvas.ZIndex="1"

8.Border边框

一个装饰控件,用于为其他元素添加边框、背景和圆角等视觉效果,不继承Panel,不属于布局控件但是具有布局功能。

8.1 基本特性

1.单一子元素容器:只能包含一个子元素 2.装饰效果:可添加边框、背景、圆角等 3.布局影响:通过Padding控制内容间距 4.可视化修饰:不改变子元素本身,只增加视觉层次

8.2 主要属性

属性 类型 说明 示例
BorderBrush Brush 边框颜色 BorderBrush="Black"
BorderThickness Thickness 边框粗细 BorderThickness="1" 或 BorderThickness="1,2,3,4"
Background Brush 背景颜色 Background="#FFEEEE"
CornerRadius CornerRadius 圆角大小 CornerRadius="5" 或 CornerRadius="10,5,10,5"
Padding Thickness 内容与边框间距 Padding="10"
Effect Effect 视觉效果(如阴影) <Border.Effect><DropShadowEffect/></Border.Effect>

8.3 使用

基本边框

<Border BorderBrush="SteelBlue" BorderThickness="2" Padding="10" Width="200" Height="80">
    <TextBlock Text="这是带边框的文本"/>
</Border>

圆角边框

<Border BorderBrush="DarkSlateGray" BorderThickness="1" Width="200" Height="80"
        CornerRadius="8" Background="LightGray" Padding="15">
    <Button Content="圆角按钮"/>
</Border>

阴影效果

<Border BorderThickness="1" CornerRadius="5" Padding="10" Width="200" Height="80"
        Background="White">
    <Border.Effect>
        <DropShadowEffect ShadowDepth="3" Opacity="0.5"/>
    </Border.Effect>
    <TextBlock Text="带阴影的边框" FontSize="16"/>
</Border>

嵌套使用

<Border BorderBrush="Black" BorderThickness="1" Margin="10" Width="200" Height="80">
    <Border BorderBrush="Gray" BorderThickness="1" Padding="5" Margin="10">
        <TextBlock Text="双层边框效果"/>
    </Border>
</Border>

视觉分隔

<StackPanel Width="200" Height="200">
    <TextBlock Text="第一部分" Margin="5"/>

    <Border BorderBrush="LightGray" BorderThickness="0,1,0,0" Margin="5"/>

    <TextBlock Text="第二部分" Margin="5"/>
</StackPanel>

图片边框

 <Border BorderBrush="Gold" BorderThickness="3" CornerRadius="3" Width="200" Height="200"
 Padding="3" Background="Black">
     <Image Source="https://www.diandiandidi.club/assets/favicon2.7203e0d9.png" Stretch="Uniform"/>
 </Border>

渐变边框

<Border Padding="1" Width="200" Height="200">
    <Border.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
            <GradientStop Color="Blue" Offset="0"/>
            <GradientStop Color="Red" Offset="1"/>
        </LinearGradientBrush>
    </Border.Background>

    <Border Background="White" Padding="10" BorderThickness="3">
        <TextBlock Text="渐变边框效果"/>
    </Border>
</Border>

单独边框

BorderThickness="3,2,1,0"(左边框),左3、上2、右1、下0

9.GridSplitter分割窗口

GridSplitter(网格分割器)是 WPF 中用于调整 Grid 行或列尺寸的专业控件,它允许用户在运行时通过拖拽来改变行高或列宽

9.1 基本特点

1.交互式调整:用户可通过鼠标拖拽实时调整行列尺寸 2.方向灵活:支持水平和垂直分割 3.精确控制:可限制调整范围和最小/最大尺寸 4.视觉反馈:拖拽时显示预览线

9.2 关键属性

属性 类型 说明 示例
ResizeDirection Enum 调整方向(Auto/Columns/Rows) ResizeDirection="Columns"
ResizeBehavior Enum 调整行为(基于位置) ResizeBehavior="PreviousAndNext"
ShowsPreview bool 是否显示拖拽预览 ShowsPreview="True"
DragIncrement double 最小拖拽增量(像素) DragIncrement="10"
KeyboardIncrement double 键盘调整增量(像素) KeyboardIncrement="20"

ResizeBehavior :

说明
BasedOnAlignment 根据对齐方式决定调整哪些列/行(默认)
CurrentAndNext 调整当前和下一列/行
PreviousAndCurrent 调整前一列/行和当前
PreviousAndNext 调整前一列/行和下一列/行

9.3 基本用法 垂直分割器(调整列宽)

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="5"/> <!-- 分割线位置 -->
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0" Text="左侧面板" Background="LightBlue"/>
    
    <!-- 垂直分割器 -->
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch"
                  Background="Gray"/>
                  
    <TextBlock Grid.Column="2" Text="右侧面板" Background="LightGreen"/>
</Grid>

水平分割器(调整行高)

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="5"/> <!-- 分割线位置 -->
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <TextBlock Grid.Row="0" Text="顶部面板" Background="LightBlue"/>
    
    <!-- 水平分割器 -->
    <GridSplitter Grid.Row="1" Height="5" VerticalAlignment="Stretch"
                  Background="Gray"/>
                  
    <TextBlock Grid.Row="2" Text="底部面板" Background="LightGreen"/>
</Grid>

9.4 限制调整范围

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MinWidth="100"/>
        <ColumnDefinition Width="5"/>
        <ColumnDefinition Width="2*" MaxWidth="300"/>
    </Grid.ColumnDefinitions>

    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch"
                  ResizeBehavior="PreviousAndNext"/>
</Grid>