百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

WPF的技术架构与优势(wpf的优缺点)

zhezhongyun 2025-06-09 07:22 2 浏览

Windows Presentation Foundation (WPF) 是一个现代化的用户界面框架,专为构建 Windows 应用程序而设计。它通过分层的技术架构和丰富的功能集,提供了全面的应用程序开发解决方案。本文将探讨 WPF 的技术架构、核心优势以及一些示例代码,以帮助开发者更好地理解和应用这一框架,其实按我最浅显的理解,WPF更接近Web的一些应用技术,或者说更早的的一种实验。

技术架构

WPF 采用分层架构设计,主要包括以下几个层次:

XAML(可扩展应用程序标记语言):WPF 的声明式 UI 语言,允许开发者以 XML 格式定义用户界面。XAML 使得界面开发更加直观和高效。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <ToolBar Grid.Row="0">
        <Button Content="新建" />
        <Button Content="打开" />
        <Separator />
        <Button Content="保存" />
    </ToolBar>
    <TabControl Grid.Row="1">
        <TabItem Header="页面1">
            <TextBox AcceptsReturn="True" />
        </TabItem>
        <TabItem Header="页面2">
            <DataGrid AutoGenerateColumns="True" />
        </TabItem>
    </TabControl>
</Grid>

依赖属性:WPF 属性系统的核心,支持属性值计算、继承和动画。依赖属性使得属性的值可以通过数据绑定、样式和动画进行动态更新。

public class ColorfulButton : Button
{
    // 定义依赖属性  
    public static readonly DependencyProperty GlowIntensityProperty =
        DependencyProperty.Register(
            "GlowIntensity",           // 属性名称  
            typeof(double),            // 属性类型  
            typeof(ColorfulButton),    // 所有者类型  
            new PropertyMetadata(0.0, OnGlowIntensityChanged) // 默认值和回调  
        );

    // CLR属性包装器  
    public double GlowIntensity
    {
        get { return (double)GetValue(GlowIntensityProperty); }
        set { SetValue(GlowIntensityProperty, value); }
    }

    // 静态构造函数  
    static ColorfulButton()
    {
        // 设置默认样式  
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(ColorfulButton),
            new FrameworkPropertyMetadata(typeof(ColorfulButton))
        );
    }

    // 当属性值变化时的回调方法  
    private static void OnGlowIntensityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var button = d as ColorfulButton;
        if (button != null)
        {
            // 创建一个渐变背景,根据发光强度调整透明度  
            var gradientBrush = new LinearGradientBrush
            {
                StartPoint = new Point(0, 0),
                EndPoint = new Point(1, 1)
            };

            // 添加渐变色点  
            gradientBrush.GradientStops.Add(new GradientStop(Colors.Blue, 0));
            gradientBrush.GradientStops.Add(new GradientStop(Colors.LightBlue, 1));

            // 设置整体透明度  
            button.Background = gradientBrush;
            button.Opacity = (double)e.NewValue;

            // 添加一些额外的视觉效果  
            button.BorderBrush = Brushes.Blue;
            button.BorderThickness = new Thickness(2);
        }
    }
}

<Window x:Class="App01.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:App01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="{x:Type local:ColorfulButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:ColorfulButton}">
                        <Border Background="{TemplateBinding Background}"   
                                BorderBrush="{TemplateBinding BorderBrush}"  
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <ContentPresenter   
                                HorizontalAlignment="Center"   
                                VerticalAlignment="Center"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <StackPanel Margin="20">
        <local:ColorfulButton   
            Content="默认发光强度"   
            Width="200"   
            Height="50"   
            Margin="0,10"/>

        <local:ColorfulButton   
            Content="高发光强度"   
            Width="200"   
            Height="50"   
            GlowIntensity="0.8"  
            Margin="0,10"/>

        <Slider   
            Minimum="0"   
            Maximum="1"   
            Value="0.5"   
            Width="200"   
            x:Name="glowSlider"/>

        <local:ColorfulButton   
            Content="动态发光按钮"   
            Width="200"   
            Height="50"   
            GlowIntensity="{Binding Value, ElementName=glowSlider}"  
            Margin="0,10"/>
    </StackPanel>
</Window>

路由事件:WPF 支持事件隧道(Preview)和冒泡(Bubble),使得事件处理更加灵活。

MVVM(模型-视图-视图模型)模式:WPF 强调 MVVM 架构,促进了数据绑定和命令的使用,使得 UI 和业务逻辑的分离更加清晰。

public class Student : INotifyPropertyChanged
{
    private string _name;
    private int _age;

    public string Name
    {
        get => _name;
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
            }
        }
    }

    public int Age
    {
        get => _age;
        set
        {
            if (_age != value)
            {
                _age = value;
                OnPropertyChanged(nameof(Age));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

public class StudentViewModel : INotifyPropertyChanged
{
    private Student _currentStudent;
    public ObservableCollection<Student> Students { get; set; }

    public Student CurrentStudent
    {
        get => _currentStudent;
        set
        {
            _currentStudent = value;
            OnPropertyChanged(nameof(CurrentStudent));
        }
    }

    public ICommand AddStudentCommand { get; private set; }

    public StudentViewModel()
    {
        Students = new ObservableCollection<Student>();
        CurrentStudent = new Student();

        AddStudentCommand = new RelayCommand(AddStudent, CanAddStudent);
    }

    private void AddStudent()
    {
        Students.Add(new Student
        {
            Name = CurrentStudent.Name,
            Age = CurrentStudent.Age
        });
        CurrentStudent = new Student(); // 重置当前学生  
    }

    private bool CanAddStudent()
    {
        return !string.IsNullOrWhiteSpace(CurrentStudent.Name) && CurrentStudent.Age > 0;
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

// 自定义命令接口实现  
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;

    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter) => _canExecute == null || _canExecute();

    public void Execute(object parameter) => _execute();
}

<Grid Margin="20">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel Grid.Row="0" Margin="0,0,0,20">
        <TextBlock Text="添加学生" FontSize="18" Margin="0,0,0,10"/>

        <StackPanel Orientation="Horizontal" Margin="0,0,0,10">
            <TextBlock Text="姓名:" VerticalAlignment="Center" Margin="0,0,10,0"/>
            <TextBox Text="{Binding CurrentStudent.Name, UpdateSourceTrigger=PropertyChanged}"   
                     Width="150" Margin="0,0,20,0"/>

            <TextBlock Text="年龄:" VerticalAlignment="Center" Margin="0,0,10,0"/>
            <TextBox Text="{Binding CurrentStudent.Age, UpdateSourceTrigger=PropertyChanged}"   
                     Width="50"/>

            <Button Content="添加"   
                    Command="{Binding AddStudentCommand}"  
                    Margin="20,0,0,0"  
                    Padding="10,5"/>
        </StackPanel>
    </StackPanel>

    <DataGrid Grid.Row="1"   
              ItemsSource="{Binding Students}"  
              AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="姓名" Binding="{Binding Name}"/>
            <DataGridTextColumn Header="年龄" Binding="{Binding Age}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

WPF的核心优势

  1. 声明式 UI:通过 XAML,开发者可以以声明的方式定义用户界面,提升了开发效率和可读性。
  2. 灵活的布局系统:WPF 提供了多种布局控件(如 Grid、StackPanel、DockPanel 等),支持响应式设计,能够适应不同屏幕尺寸和分辨率。
  3. 强大的数据绑定机制:WPF 的数据绑定功能使得 UI 和数据模型之间的交互变得简单而高效,支持双向绑定和数据转换。
  4. 样式和模板系统:WPF 允许开发者通过样式和控制模板自定义控件的外观,提升了应用程序的可定制性。
  5. 基于 DirectX 的图形渲染:WPF 利用 DirectX 提供高性能的图形渲染,支持复杂的图形和动画效果。

示例:数据可视化应用

以下是一个简单的数据可视化示例,展示了如何使用 WPF 创建一个包含图表和控制面板的窗口。

<Window x:Class="WpfApp.DataVisualizationWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        Title="数据可视化示例">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <ComboBox Width="120" Margin="5" ItemsSource="{Binding ChartTypes}" SelectedItem="{Binding SelectedChartType}"/>
            <Button Content="刷新数据" Command="{Binding RefreshCommand}" Margin="5"/>
            <Button Content="导出" Command="{Binding ExportCommand}" Margin="5"/>
        </StackPanel>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Border Grid.Column="0" BorderBrush="Gray" BorderThickness="1" Margin="5">
                <Canvas x:Name="ChartCanvas">
                    <!-- 动态生成的图表内容 -->
                </Canvas>
            </Border>
            <StackPanel Grid.Column="1" Width="150" Margin="5">
                <ItemsControl ItemsSource="{Binding Legends}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Rectangle Width="16" Height="16" Fill="{Binding Color}" Margin="5"/>
                                <TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </Grid>
    </Grid>
</Window>

结论

WPF 是一个功能强大的 UI 框架,凭借其分层架构和丰富的功能集,能够帮助开发者构建出既美观又高效的 Windows 应用程序。通过 XAML、依赖属性、MVVM 模式等特性,WPF 提供了灵活的开发方式,极大地提升了开发效率和应用质量。无论是企业级应用还是个人项目,WPF 都是一个值得考虑的选择。

相关推荐

Renaming column names in Pandas

技术背景在数据处理过程中,经常需要对数据框(DataFrame)的列名进行重命名,以满足数据分析、可视化或其他处理的需求。Pandas是Python中用于数据处理和分析的强大库,提供了多种重命名...

JSA宏教程WPS表格常用内置对象——应用程序(Application)对象

一、关于应用程序Application对象Application对象就是一个运行着的WPS表格(即ET)应用程序,它是整个应用程序根对象,在它之上没有其他程序对象了。ET在WPS的文件夹中的图标如下:...

Pandas通过columns属性访问、修改和删除列

在pandas中,DataFrame的列可以使用columns属性进行访问、修改或删除。以下是使用columns属性访问DataFrame列的示例代码:importpandasa...

excel的高级用法——宏,原来如此实用

使用excel时,直接手动计算或者输入公式,你会感到很苦恼或者操作很繁琐,如果使用vba直接输出结果,虽然效率很高,但是不够直观。excel宏最方便的用法是作为公式里的函数使用,打开宏编辑器,编写一个...

CSS grid-template-columns属性探讨|给你代码

CSSgrid布局CSSgrid布局是一种很强大的布局,兼容性如上表所示,表现在控制台里,你可以清楚看到他的内部每一个块都由一个虚线方块组成。他的每行每列都会生产一个单元格,而划分他们之间的线称为网...

7K star!Text2SQL还不够?试试RAG2SQL的开源工具

查询数据库离不开SQL,那如何快速构建符合自己期望的SQL呢?AI发展带来了Text2SQL的能力,众多产品纷纷提供了很好的支持。今天我们分享一个开源项目,它在Text2SQL的基础上还要继续提高,通...

用Python把表格做成web可视化图表

Python中有一个streamlit库,Streamlit的美妙之处在于您可以直接在Python中创建Web应用程序,而无需了解HTML、CSS或JavaScrip,今天我们就用st...

鸿蒙开发:使用Circle绘制圆形(鸿蒙圆角)

前言本文基于Api13上篇文章,我们使用Rect组件实现了矩形效果,本篇文章,我们继续探究几何图形的中圆形,实现矩形有多种形式,同样,圆形,也是有多种形式,在上篇的文章中也简单的做了几个案例,比如,我...

pandas读取Excel数据(.xlsx和.xls)

Python,速成心法敲代码,查资料,问Ai练习,探索,总结,优化★★★★★★★★★★Python教程:PyCharm安装过程中遇到的中英...

WPF - 4.布局(wpf 表单布局)

摘要WPF布局原则一个窗口中只能包含一个元素屏幕适应程序,不要显示设置的元素(控件)的尺寸,可以设置最小或者最大尺寸不应使用坐标设置元素的位置可以嵌套布局容器正文Grid面板通过Grid.RowDef...

前端开发避坑指南:每天都能用的 CSS3/Less/Sass 实战技巧

在前端开发这条路上,CSS3、Less和Sass就像三个形影不离的好兄弟。它们既能帮你打造出惊艳的页面效果,也会偶尔给你“挖坑”。今天就分享几个我在项目里摸爬滚打总结出的实战技巧,全是干货,拿...

WPF 实现描点导航(wps描点作图)

WPF实现描点导航控件名:NavScrollPanel作者:WPFDevelopersOrg-驚鏵原文链接[1]:https://github.com/WPFDevelopersOrg/WPF...

WPS表格自动绘制像素风格营销宣传海报文档

先看效果原图WPS表格(类Excel)效果,这不是贴图哦操作流程分解图片为BGR数值的二维数组化的CSV将二维数组的CSV导入数据,数据-导入-选择数据源-分隔符号-逗号-完成插入脚本,开发工具-WP...

Python读写docx文件(python读文档)

Python读写docx文件Python读写word文档有现成的库可以处理pipinstallpython-docx安装一下。https://python-docx.readthedocs.io/...

UWP开发入门(十七)--判断设备类型及响应VirtualKey

蜀黍我做的工作跟IM软件有关,UWP同时会跑在电脑和手机上。电脑和手机的使用习惯不尽一致,通常我倾向于根据窗口尺寸来进行布局的变化,但是特定的操作习惯是依赖于设备类型,而不是屏幕尺寸的,比如聊天窗口的...