WPF 开发从入门到进阶(五)

news2025/3/19 9:38:29

一、WPF 简介与开发环境搭建

1.1 WPF 概述

Windows Presentation Foundation(WPF)是微软推出的用于构建 Windows 桌面应用程序的强大 UI 框架。它融合了矢量图形、动画、多媒体等多种技术,能让开发者创建出具有高度视觉吸引力和交互性的应用界面。相较于传统的 Windows Forms,WPF 更注重界面的设计和用户体验,并且提供了更好的布局和样式控制能力。

1.2 开发环境搭建

1.2.1 安装 Visual Studio

访问微软官方网站下载并安装 Visual Studio。在安装过程中,选择 “.NET 桌面开发” 工作负载,其中包含了开发 WPF 应用所需的工具和框架。安装完成后,启动 Visual Studio。

1.2.2 创建 WPF 项目

打开 Visual Studio,选择 “创建新项目”。在搜索框中输入 “WPF 应用”,根据需求选择合适的项目模板,如 “WPF 应用(.NET 6.0)”,然后输入项目名称和存储位置,点击 “创建” 按钮。

二、XAML 基础与界面设计

2.1 XAML 基础语法

2.1.1 元素和属性

XAML 使用 XML 标签来定义界面元素,元素名称对应着.NET 类型。每个元素可以有多个属性,用于设置其外观和行为。例如:

<Button Content="Click Me" Width="120" Height="40" />

这里的 <Button> 是元素,ContentWidth 和 Height 是属性。

2.1.2 嵌套元素

元素可以嵌套,形成层次结构,用于构建复杂的界面布局。例如:

<StackPanel>
    <TextBlock Text="Welcome to WPF!" FontSize="20" />
    <Button Content="Explore" Width="100" Height="30" />
</StackPanel>

<StackPanel> 是一个容器元素,包含了一个 <TextBlock> 和一个 <Button>

2.1.3 命名空间

XAML 文件需要定义命名空间来引用不同的类型。通常在根元素中定义默认命名空间和其他必要的命名空间。例如:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Main Window" Height="450" Width="800">
    <!-- 窗口内容 -->
</Window>

默认命名空间 http://schemas.microsoft.com/winfx/2006/xaml/presentation 包含了 WPF 的核心 UI 元素类型,xmlns:x 引用的命名空间用于 XAML 语言本身的特性,如 x:Class 用于指定代码隐藏文件中对应的类。

2.2 常用布局容器

2.2.1 Grid

Grid 是一个强大的布局容器,它将界面划分为行和列的网格,子元素可以通过 Grid.Row 和 Grid.Column 附加属性指定在网格中的位置。例如:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Button Content="Top - Left" Grid.Row="0" Grid.Column="0" />
    <Button Content="Top - Right" Grid.Row="0" Grid.Column="1" />
    <Button Content="Bottom - Left" Grid.Row="1" Grid.Column="0" />
    <Button Content="Bottom - Right" Grid.Row="1" Grid.Column="1" />
</Grid>
2.2.2 StackPanel

StackPanel 按照水平或垂直方向排列子元素,通过 Orientation 属性设置排列方向,默认是垂直方向。例如:

<StackPanel Orientation="Horizontal">
    <Button Content="Button 1" />
    <Button Content="Button 2" />
    <Button Content="Button 3" />
</StackPanel>
2.2.3 WrapPanel

WrapPanel 子元素会按照指定的方向依次排列,当一行或一列排满时,会自动换行或换列。例如:

<WrapPanel>
    <Button Content="Short Button" />
    <Button Content="A Longer Button" />
    <Button Content="Another Button" />
</WrapPanel>
2.2.4 DockPanel

DockPanel 子元素可以停靠在面板的边缘,通过 DockPanel.Dock 附加属性设置停靠位置。例如:

<DockPanel>
    <Button Content="Top" DockPanel.Dock="Top" />
    <Button Content="Bottom" DockPanel.Dock="Bottom" />
    <Button Content="Left" DockPanel.Dock="Left" />
    <Button Content="Right" DockPanel.Dock="Right" />
    <Button Content="Center" />
</DockPanel>

2.3 常用控件

2.3.1 Button

Button 是最常用的控件之一,用于触发操作。可以通过 Content 属性设置按钮显示的文本或其他内容,通过 Click 事件处理按钮的点击操作。例如:

<Button Content="Submit" Click="Button_Click" />

在代码隐藏文件中添加事件处理方法:

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Button clicked!");
}
2.3.2 TextBox

TextBox 用于用户输入文本。可以通过 Text 属性获取或设置文本内容,通过 TextChanged 事件响应文本的变化。例如:

<TextBox TextChanged="TextBox_TextChanged" />

在代码隐藏文件中添加事件处理方法:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = (TextBox)sender;
    string text = textBox.Text;
    // 处理文本变化逻辑
}
2.3.3 ComboBox

ComboBox 是下拉列表框,用户可以从预定义的选项中选择一个值。可以通过 ItemsSource 属性绑定数据源,通过 SelectedItem 或 SelectedValue 属性获取当前选中的项。例如:

<ComboBox ItemsSource="{Binding MyItems}" SelectedValue="{Binding SelectedItem}" />

在代码隐藏文件或 ViewModel 中设置数据源和属性:

public class ViewModel
{
    public ObservableCollection<string> MyItems { get; set; }
    public string SelectedItem { get; set; }

    public ViewModel()
    {
        MyItems = new ObservableCollection<string>() { "Option 1", "Option 2", "Option 3" };
    }
}
2.3.4 CheckBox

CheckBox 用于表示布尔值的选择状态。可以通过 IsChecked 属性获取或设置复选框的选中状态,通过 Checked 和 Unchecked 事件响应状态变化。例如:

<CheckBox Content="Remember Me" IsChecked="{Binding IsRememberMe}" />

在 ViewModel 中定义属性:

private bool _isRememberMe;
public bool IsRememberMe
{
    get { return _isRememberMe; }
    set
    {
        _isRememberMe = value;
        OnPropertyChanged(nameof(IsRememberMe));
    }
}
2.3.5 RadioButton

RadioButton 是单选按钮,一组单选按钮中只能有一个被选中。通过 GroupName 属性将多个单选按钮分组,通过 IsChecked 属性判断是否被选中。例如:

<StackPanel>
    <RadioButton Content="Male" GroupName="Gender" IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter=Male}" />
    <RadioButton Content="Female" GroupName="Gender" IsChecked="{Binding Gender, Converter={StaticResource GenderConverter}, ConverterParameter=Female}" />
</StackPanel>

这里使用了一个转换器 GenderConverter 来将 ViewModel 中的 Gender 属性值与单选按钮的选中状态进行转换。

三、数据绑定与 MVVM 模式

3.1 数据绑定基础

3.1.1 绑定概念

数据绑定是 WPF 的核心特性之一,它建立了 UI 元素(绑定目标)和数据源(绑定源)之间的连接,使得 UI 元素能够自动反映数据源的变化,并且可以将用户在 UI 上的操作反馈到数据源。

3.1.2 绑定模式

  • OneWay:数据从绑定源流向绑定目标,当绑定源属性值发生变化时,绑定目标属性会自动更新,但绑定目标的变化不会影响绑定源。常用于显示只读数据的场景,如显示数据库中的记录。
<TextBlock Text="{Binding ReadOnlyProperty, Mode=OneWay}" />

  • TwoWay:数据在绑定源和绑定目标之间双向流动,当绑定源属性值变化时,绑定目标更新;当绑定目标属性值变化时,绑定源也会相应更新。常用于需要用户输入并更新数据的场景,如编辑表单。
<TextBox Text="{Binding EditableProperty, Mode=TwoWay}" />

  • OneTime:数据在初始化时从绑定源流向绑定目标,之后绑定源的变化不会再影响绑定目标。适用于数据在应用程序运行过程中不会改变的情况,如显示应用程序的版本号。
<TextBlock Text="{Binding AppVersion, Mode=OneTime}" />
3.1.3 实现数据绑定

  • 创建数据源:通常创建一个 ViewModel 类作为数据源。ViewModel 类应该实现 INotifyPropertyChanged 接口,以便在属性值发生变化时通知绑定目标更新。例如:
public class UserViewModel : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged(nameof(Name));
        }
    }

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

  • 设置 DataContext:在窗口或控件的代码隐藏文件中,将 ViewModel 的实例设置为 DataContext,这样 XAML 中的绑定就可以找到对应的数据源。
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        UserViewModel viewModel = new UserViewModel();
        DataContext = viewModel;
    }
}

  • 在 XAML 中进行绑定:使用 Binding 标记扩展将 UI 元素的属性绑定到 ViewModel 的属性上。
<TextBox Text="{Binding Name}" />

3.2 MVVM 模式

3.2.1 MVVM 概述

MVVM(Model - View - ViewModel)是一种设计模式,用于分离 UI 设计和业务逻辑。它将视图(View)、视图模型(ViewModel)和模型(Model)分离,提高了代码的可维护性和可测试性。

  • Model:表示应用程序的数据和业务逻辑,如数据库实体、业务规则等。
  • View:负责界面的呈现,即 XAML 文件定义的 UI 元素。
  • ViewModel:作为 View 和 Model 之间的桥梁,负责处理视图的交互逻辑和数据转换,实现了视图和模型的解耦。
3.2.2 MVVM 示例

以下是一个简单的 MVVM 示例,实现一个用户信息显示和编辑的功能。

Model 类

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

ViewModel 类

public class UserViewModel : INotifyPropertyChanged
{
    private User _user;
    public User User
    {
        get { return _user; }
        set
        {
            _user = value;
            OnPropertyChanged(nameof(User));
        }
    }

    public UserViewModel()
    {
        User = new User { Name = "John Doe", Age = 30 };
    }

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

View(XAML)

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="User Info" Height="300" Width="400">
    <Grid>
        <StackPanel Margin="20">
            <TextBlock Text="Name:" />
            <TextBox Text="{Binding User.Name, Mode=TwoWay}" />
            <TextBlock Text="Age:" />
            <TextBox Text="{Binding User.Age, Mode=TwoWay}" />
        </StackPanel>
    </Grid>
</Window>

代码隐藏文件(设置 DataContext)

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        UserViewModel viewModel = new UserViewModel();
        DataContext = viewModel;
    }
}

四、样式、模板与资源管理

4.1 样式基础

4.1.1 样式定义

样式是一种用于集中设置 UI 元素属性的机制,可以将一组属性应用到多个元素上,实现统一的外观风格。样式可以定义在资源字典中,也可以直接在 XAML 文件中定义。例如:

<Window.Resources>
    <Style x:Key="MyButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="LightBlue"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="Padding" Value="10"/>
    </Style>
</Window.Resources>
<Button Style="{StaticResource MyButtonStyle}" Content="Styled Button"/>
4.1.2 样式继承

样式可以继承其他样式的属性,通过 BasedOn 属性来实现。例如:

<Window.Resources>
    <Style x:Key="BaseButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="LightGray"/>
        <Setter Property="Foreground" Value="Black"/>
    </Style>
    <Style x:Key="DerivedButtonStyle" TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
        <Setter Property="FontSize" Value="18"/>
    </Style>
</Window.Resources>
<Button Style="{StaticResource DerivedButtonStyle}" Content="Inherited Styled Button"/>

4.2 模板基础

4.2.1 ControlTemplate

ControlTemplate 用于自定义控件的外观。它可以完全改变控件的可视化结构,而不仅仅是设置属性。例如,自定义一个按钮的模板:

<Window.Resources>
    <ControlTemplate x:Key="CustomButtonTemplate" TargetType="Button">
        <Border x:Name="border" Background="{TemplateBinding Background}" 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="LightGray"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter TargetName="border" Property="Background" Value="DarkGray"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</Window.Resources>
<Button Template="{StaticResource CustomButtonTemplate}" Content="Custom Button"/>
4.2.2 DataTemplate

DataTemplate 用于定义数据项的呈现方式。当我们将一个集合绑定到一个列表控件(如 ListViewComboBox 等)时,DataTemplate 可以决定每个数据项在界面上的显示形式。例如:

<Window.Resources>
    <DataTemplate x:Key="PersonDataTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" Margin="5"/>
            <TextBlock Text="{Binding Age}" Margin="5"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding Persons}" ItemTemplate="{StaticResource PersonDataTemplate}"/>

4.3 资源字典

资源字典是一种用于集中管理样式、模板、画笔等资源的机制。可以将资源字典定义在单独的 .xaml 文件中,然后在多个 XAML 文件中引用。

4.3.1 创建资源字典文件

创建一个名为 MyResources.xaml 的文件,内容如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="SharedButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Orange"/>
        <Setter Property="Foreground" Value="White"/>
    </Style>
    <DataTemplate x:Key="SharedDataTemplate">
        <TextBlock Text="{Binding SomeProperty}" Foreground="Red"/>
    </DataTemplate>
</ResourceDictionary>
4.3.2 在 XAML 文件中引用资源字典
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MyResources.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
<Button Style="{StaticResource SharedButtonStyle}" Content="Shared Styled Button"/>
<ListBox ItemsSource="{Binding SomeCollection}" ItemTemplate="{StaticResource SharedDataTemplate}"/>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2317710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OctoTools:一个具有复杂推理可扩展工具的智体框架

25年2月来自斯坦福大学的论文“OctoTools: An Agentic Framework with Extensible Tools for Complex Reasoning”。 解决复杂的推理任务可能涉及视觉理解、域知识检索、数值计算和多步骤推理。现有方法使用外部工具增强大语言模型 (LLM)&#xff0c;但仅限于专业领域、有限的…

Canary

定义&#xff1a; Canary是一种用以防护栈溢出的保护机制。 原理&#xff1a; 是在一个函数的入口处&#xff0c;先从fs/gs寄存器中取出一个4字节&#xff08;eax,四字节通常是32位的文件&#xff09;或者8字节&#xff08;rax&#xff0c;通常是64位的文件&#xff09;的值…

c++领域展开第十七幕——STL(vector容器的模拟实现以及迭代器失效问题)超详细!!!!

文章目录 前言vector——基本模型vector——迭代器模拟实现vector——容量函数以及push_back、pop_backvector——默认成员函数vector——运算符重载vector——插入和删除函数vector——实现过程的问题迭代器失效memcpy的浅拷贝问题 总结 前言 上篇博客我们已经详细介绍了vecto…

BUUCTF Pwn babyheap_0ctf_2017 Unsorted bin attack部分

checksec exeinfo 开启了全保护 64位 查看函数&#xff1a; 堆题 增删查改齐了 可以在编辑堆的时候重新设置大小 存在堆溢出 delete函数的指针清零了 无UAF 想法是通过unsorted bin泄露libc基址&#xff1a; from pwn import *p process(./babyheap) #p remote("node…

【C++指南】内存管理完全手册:new/delete

&#x1f31f; 各位看官好&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; &#x1f680; 今天来学习C内存管理的相关知识。 &#x1f44d; 如果觉得这篇文章有帮助&#xff0c;欢迎您一键三连&#xff0c;分享…

Vue3组合式函数(滚动监测 useScroll)

主要用于实时监测目标元素滚动位置及状态 工具函数源码 /*** 组合式函数* 实时监测目标元素滚动位置及状态** 自定义钩子用于处理滚动事件和状态* param target 滚动目标元素&#xff0c;可以是 Ref、HTMLElement、Window 或 Document&#xff0c;默认为 window* param throt…

Vue.js+Element UI 登录界面开发详解【附源码】

成果图&#xff1a; 一、技术架构解析 本登录模块采用前后端分离架构&#xff0c;前端基于Vue.jsElement UI实现交互逻辑&#xff0c;主要包含以下技术要点&#xff1a; ​组件化开发 - 采用单文件组件形式组织代码​响应式设计 - 实现多终端适配​状态管理 - 使用sessionSto…

瑞幸需要宇树科技

吃不到“星巴克红利”&#xff0c;瑞幸活成“Manner”。 作者|古廿 编辑|杨舟 “是不是又要开始3月革命了。”有瑞幸员工透露&#xff0c;今年开始瑞幸加强了系统排班的执行力度。新的排班体系下&#xff0c;要求各时段门店实际值班人员和排班系统一致。如果需要调整&#xf…

linux 命令 vim

以下是 Linux 中 Vim 编辑器的核心命令总结&#xff0c;分为基础操作、高效编辑技巧和实用场景&#xff0c;助你快速掌握 1. 启动与退出 命令说明vim 文件名打开或新建文件vim 行号 文件名打开文件并跳转到指定行&#xff08;如 vim 10 file.txt&#xff09;:q退出 Vim&#…

解决MySQL字符集冲突引发的“Illegal mix of collations”错误

引言 在开发过程中&#xff0c;我们常常会遇到数据库层面的字符集兼容性问题。本文将通过一个典型的案例&#xff0c;分析因字符集不匹配导致的 Illegal mix of collations 错误&#xff0c;并提供完整的解决方案&#xff0c;帮助开发者彻底规避此类问题。 问题现象 假设我们…

Vue中的publicPath释义

publicPath 部署应用包时的基本URL。用法和 webpack 本身的 output.publicPath 一致&#xff0c;但是 Vue CLI 在一些其他地方也需要用到这个值&#xff0c;所以请始终使用 publicPath 而不要直接修改 webpack 的 output.publicPath。 默认情况下&#xff0c;Vue CLI 会假设你…

新造车不再比拼排名,恰是曲终人散时,剩者为王

据称新能源汽车周销量不再发布&#xff0c;这可能也预示着新造车终于到了给出答案的时候了&#xff0c;新造车企业前三强已基本确立&#xff0c;其余那些落后的车企已很难有突围的机会&#xff0c;而特斯拉无疑是其中的最大赢家。 3月份第一周的数据显示&#xff0c;销量最高的…

博客迁移----宝塔面板一键迁移遇到问题

前景 阿里云轻量级服务器到期了&#xff0c;又免费领了个ESC&#xff0c; 安转了宝塔面板。现在需要迁移数据&#xff0c;使用宝塔面板一键迁移功能&#xff0c;完成了数据的迁移&#xff0c;改了域名的解析&#xff0c;现在进入博客是显示502 bad grateway 宝塔搬家参考链接…

大数据处理最容易的开源平台

大数据处理最容易的开源平台可以从多个角度进行分析&#xff0c;包括易用性、灵活性、成本效益以及社区支持等方面。 Apache Spark Apache Spark 是一个广泛使用的开源大数据处理框架&#xff0c;以其快速、通用和易于使用的特点而著称。它支持多种编程语言&#xff08;如 Scal…

Dify 使用 - 创建 翻译 工作流

文章目录 1、选择 模板2、设置 和 基本使用3、运行应用 1、选择 模板 2、设置 和 基本使用 翻译模板 自带了系统提示词&#xff0c;你也可以修改 3、运行应用 右上角 点击 发布 – 更新&#xff0c;运行应用&#xff0c;就可以在新的对话界面中使用此功能 2025-03-18&#x…

TreelabPLMSCM数字化供应链解决方案0608(61页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;TreelabPLMSCM 数字化供应链解决方案 0608 在当今快速变化的市场环境中&#xff0c;企业面临着诸多挑战&#xff0c;Treelab 数智化 PLM_SCM 行业解决方案应运而生。该方案聚焦市场趋势与行业现状&#xff0c;致力于解…

LogicFlow介绍

LogicFlow介绍 LogicFlow是一款流程图编辑框架&#xff0c;提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端自定义开发各种逻辑编排场景&#xff0c;如流程图、ER图、BPMN流程等。在工作审批流配置、机器人逻辑编排、无代码平…

[蓝桥杯 2023 省 B] 飞机降落

[蓝桥杯 2023 省 B] 飞机降落 题目描述 N N N 架飞机准备降落到某个只有一条跑道的机场。其中第 i i i 架飞机在 T i T_{i} Ti​ 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 D i D_{i} Di​ 个单位时间&#xff0c;即它最早可以于 T i T_{i} Ti​ 时刻…