当前位置: 首页 > article >正文

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

一、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.kler.cn/a/591811.html

相关文章:

  • JAVA EE(9)——线程安全——锁策略CAS
  • 【安全运营】用户与实体行为分析(UEBA)浅析
  • Lua语言的自动化测试
  • 【python】带有\n的json字符串,如何优雅打印
  • goweb中文件上传和文件下载
  • 监控视频联网平台在智慧水利中的应用
  • 技术革命、需求升级与商业生态迭代——基于开源AI大模型与智能商业范式的创新研究
  • 深入理解静态与动态代理设计模式:从理论到实践
  • Oracle常见系统函数
  • 华为供应链的变革模式和方法P105(105页PPT)(文末有下载方式)
  • 3D视觉相机引导机器人的原理
  • MongoDB下载安装
  • 深度学习框架PyTorch——从入门到精通(4)数据转换
  • vue/react前端项目打包的时候加上时间,防止后端扯皮
  • Python 视频爬取教程
  • 【SpringMVC】深入解析基于Spring MVC与AJAX的用户登录全流程——参数校验、Session管理、前后端交互与安全实践
  • 【eNSP实战】旁挂二层组网—隧道转发
  • 【在数轴上找最优位置,使移动距离最短】
  • 在NET6项目中报错,未能在命名空间System.Data.SqlClient中找到类型名SqlCommand,解决办法
  • Linux系统移植篇(十一)Linux 内核启动流程