目录

WPF高级-WPF-与-MVVM-设计模式构建可维护的大型应用架构

WPF高级 | WPF 与 MVVM 设计模式:构建可维护的大型应用架构

https://i-blog.csdnimg.cn/direct/0ade8a747a9c457485662890894d08ab.gif#pic_center

https://i-blog.csdnimg.cn/direct/14bef05ddd1a4343a8ec720c13104a05.gif#pic_center

WPF高级 | WPF 与 MVVM 设计模式:构建可维护的大型应用架构

WPF高级 | WPF 与 MVVM 设计模式:构建可维护的大型应用架构 ,在当今的软件开发领域,构建大型、可维护且易于扩展的应用程序是开发者们面临的重要挑战。Windows Presentation Foundation(WPF)作为微软新一代的图形界面技术,提供了强大的可视化设计和交互能力。而 Model - View - ViewModel(MVVM)设计模式则为 WPF 应用程序的架构设计提供了清晰的思路和规范,有助于提高代码的可维护性、可测试性和可扩展性。本文将深入探讨 WPF 与 MVVM 设计模式的结合,通过丰富的代码示例和详细的概念解释,帮助读者掌握如何利用这两者构建健壮的大型应用架构。

一、前言

在数字浪潮汹涌澎湃的时代,程序开发宛如一座神秘而宏伟的魔法城堡,矗立在科技的浩瀚星空中。代码的字符,似那闪烁的星辰,按照特定的轨迹与节奏,组合、交织、碰撞,即将开启一场奇妙且充满无限可能的创造之旅。当空白的文档界面如同深邃的宇宙等待探索,程序员们则化身无畏的星辰开拓者,指尖在键盘上轻舞,准备用智慧与逻辑编织出足以改变世界运行规则的程序画卷,在 0 和 1 的二进制世界里,镌刻下属于人类创新与突破的不朽印记。

在当今数字化时代,桌面应用程序的用户界面(UI)设计至关重要,它直接影响着用户体验与产品的竞争力。而 WPF(Windows Presentation Foundation)作为微软推出的一款强大的 UI 框架,其布局系统更是构建精美界面的核心要素。WPF 布局系统为开发者提供了丰富多样的布局方式,能够轻松应对各种复杂的界面设计需求,无论是简洁明了的工具软件,还是功能繁杂的企业级应用,都能借助其打造出令人惊艳的视觉效果与流畅的交互体验。

WPF从入门到精通专栏,旨在为读者呈现一条从对 WPF(Windows Presentation Foundation)技术懵懂无知到精通掌握的学习路径。首先从基础入手,介绍 WPF 的核心概念,涵盖其独特的架构特点、开发环境搭建流程,详细解读布局系统、常用控件以及事件机制等基础知识,帮助初学者搭建起对 WPF 整体的初步认知框架。随着学习的深入,进阶部分聚焦于数据绑定、样式模板、动画特效等关键知识点,进一步拓展 WPF 开发的能力边界,使开发者能够打造出更为个性化、交互性强的桌面应用界面。高级阶段则涉及自定义控件开发、MVVM 设计模式应用、多线程编程等深层次内容,助力开发者应对复杂的业务需求,构建大型且可维护的应用架构。同时,通过实战项目案例解析,展示如何将所学知识综合运用到实际开发中,从需求分析到功能实现再到优化测试,全方位积累实践经验。此外,还探讨了性能优化、与其他技术集成以及安全机制等拓展性话题,让读者对 WPF 技术在不同维度有更深入理解,最终实现对 WPF 技术的精通掌握,具备独立开发高质量桌面应用的能力。

https://i-blog.csdnimg.cn/direct/45c29ac24919487dbc5cf7b6dbee90e9.png#pic_center

二、WPF 基础回顾

2.1 WPF 概述

WPF 是基于.NET Framework 的图形系统,它采用了一种全新的呈现模型,利用 DirectX 技术进行硬件加速渲染,从而提供了高质量的图形显示效果。WPF 支持多种媒体类型,如 2D 和 3D 图形、音频、视频等,并且提供了丰富的布局容器和控件,使得开发者能够创建出极具吸引力和交互性的用户界面。

2.2 WPF 的核心特性

  • XAML(可扩展应用程序标记语言)

XAML 是一种用于描述用户界面的声明性语言,它将界面的定义与代码逻辑分离,使得界面设计更加直观和易于维护。例如,下面是一个简单的 WPF 窗口定义:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="My First WPF Window" Height="350" Width="525">
    <Grid>
        <Button Content="Click Me!" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>

在这个例子中,标签定义了一个窗口,是布局容器,是一个按钮控件。通过 XAML,我们可以清晰地看到界面的结构和组成部分。

  • 依赖属性和路由事件

依赖属性是 WPF 中的一种特殊属性,它具有很多优点,如支持数据绑定、样式设置、动画等。例如,Button的Content属性就是一个依赖属性。

public class MyButton : Button
{
    public static readonly DependencyProperty MyCustomPropertyProperty =
        DependencyProperty.Register("MyCustomProperty", typeof(string), typeof(MyButton), new PropertyMetadata(""));

    public string MyCustomProperty
    {
        get { return (string)GetValue(MyCustomPropertyProperty); }
        set { SetValue(MyCustomPropertyProperty, value); }
    }
}

路由事件是一种能够在元素树中传播的事件,它使得事件处理更加灵活。例如,Button的Click事件就是一个路由事件。

<Button Content="Click Me!" Click="Button_Click" HorizontalAlignment="Center" VerticalAlignment="Center"/>

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Button Clicked!");
}
  • 数据绑定

数据绑定是 WPF 的一个核心特性,它允许将数据源与 UI 元素进行绑定,使得 UI 元素能够自动反映数据源的变化。例如,我们可以将一个TextBox的Text属性绑定到一个 ViewModel 中的属性。

<TextBox Text="{Binding UserName}" />

public class ViewModel
{
    private string _userName;
    public string UserName
    {
        get { return _userName; }
        set
        {
            _userName = value;
            // 这里可以添加属性变更通知的代码,例如使用INotifyPropertyChanged接口
        }
    }
}

三、MVVM 设计模式详解

3.1 MVVM 模式的基本概念

MVVM 模式由三个主要部分组成:Model(模型)、View(视图)和 ViewModel(视图模型)。

  • Model :表示应用程序的数据和业务逻辑。它包含了应用程序所需要的数据结构和操作这些数据的方法。例如,在一个用户管理系统中,User类就是一个 Model,它包含了用户的姓名、年龄、邮箱等信息。
public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}
  • View :负责呈现用户界面,它通过数据绑定与 ViewModel 进行交互。View 只关注如何将数据展示给用户,而不涉及业务逻辑。在 WPF 中,View 通常是由 XAML 文件定义的窗口或控件。
  • ViewModel :作为 ViewModel 之间的桥梁,它负责将 Model 的数据转换为 View 可以使用的格式,并处理 ViewModel 之间的交互。 ViewModel 包含了 View 所需要的数据和命令,同时实现了 INotifyPropertyChanged 接口来通知 View 数据的变化。

3.2 INotifyPropertyChanged 接口

INotifyPropertyChanged 接口是 MVVM 模式中实现数据变更通知的关键。当 ViewModel 中的属性值发生变化时,通过实现该接口的 PropertyChanged 事件,View 可以及时更新显示。

public class ViewModel : INotifyPropertyChanged
{
    private string _userName;
    public string UserName
    {
        get { return _userName; }
        set
        {
            _userName = value;
            OnPropertyChanged(nameof(UserName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

3.3 命令(ICommand)

在 MVVM 模式中,命令是一种将用户操作(如按钮点击)与 ViewModel 中的方法关联起来的机制。WPF 提供了ICommand接口来实现命令。

public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;

    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }

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

在 ViewModel 中,可以定义一个命令属性:

public class ViewModel
{
    public ICommand SaveCommand { get; private set; }

    public ViewModel()
    {
        SaveCommand = new RelayCommand(Save);
    }

    private void Save()
    {
        // 保存数据的逻辑
    }
}

在 View 中,可以将按钮的Command属性绑定到 ViewModel 的命令:

<Button Content="Save" Command="{Binding SaveCommand}" />

四、WPF 与 MVVM 的结合应用

4.1 创建一个简单的 WPF MVVM 应用

  • 创建项目

首先,在 Visual Studio 中创建一个新的 WPF 应用程序项目。

  • 定义 Model

创建一个User类作为 Model:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}
  • 创建 ViewModel

创建一个UserViewModel类作为 ViewModel,实现INotifyPropertyChanged接口,并定义与User类相关的属性和命令。

public class UserViewModel : INotifyPropertyChanged
{
    private User _user;

    public UserViewModel()
    {
        _user = new User();
        SaveCommand = new RelayCommand(Save);
    }

    public string Name
    {
        get { return _user.Name; }
        set
        {
            _user.Name = value;
            OnPropertyChanged(nameof(Name));
        }
    }

    public int Age
    {
        get { return _user.Age; }
        set
        {
            _user.Age = value;
            OnPropertyChanged(nameof(Age));
        }
    }

    public string Email
    {
        get { return _user.Email; }
        set
        {
            _user.Email = value;
            OnPropertyChanged(nameof(Email));
        }
    }

    public ICommand SaveCommand { get; private set; }

    private void Save()
    {
        // 保存用户数据的逻辑,例如将数据保存到数据库
        MessageBox.Show($"User saved: Name={Name}, Age={Age}, Email={Email}");
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

在 XAML 文件中设计用户界面,并将界面元素绑定到 ViewModel 的属性和命令。

<Window x:Class="WpfMVVMApp.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:WpfMVVMApp"
        mc:Ignorable="d"
        Title="User Management" Height="350" Width="525">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBox Text="{Binding Name}" PlaceholderText="Name" Margin="5"/>
            <TextBox Text="{Binding Age}" PlaceholderText="Age" Margin="5"/>
            <TextBox Text="{Binding Email}" PlaceholderText="Email" Margin="5"/>
            <Button Content="Save" Command="{Binding SaveCommand}" Margin="5"/>
        </StackPanel>
    </Grid>
</Window>
  • 绑定 ViewModel

在代码后台将 ViewModel 与 View 进行绑定:

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

4.2 数据验证

在实际应用中,数据验证是非常重要的。在 MVVM 模式下,可以使用IDataErrorInfo接口来实现数据验证。

  • 修改 ViewModel

让UserViewModel实现IDataErrorInfo接口:

public class UserViewModel : INotifyPropertyChanged, IDataErrorInfo
{
    // 其他代码不变

    public string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case nameof(Name):
                    if (string.IsNullOrEmpty(Name))
                    {
                        return "Name cannot be empty";
                    }
                    break;
                case nameof(Age):
                    if (Age < 0 || Age > 120)
                    {
                        return "Age should be between 0 and 120";
                    }
                    break;
                case nameof(Email):
                    if (!Regex.IsMatch(Email, @"^[\w -]+([\w -]+)*@([\w -]+)+[a-zA - Z]{2,7}$"))
                    {
                        return "Invalid email format";
                    }
                    break;
            }
            return null;
        }
    }

    public string Error => null;
}
  • 在 View 中显示验证错误

在 XAML 中,可以使用Validation.ErrorTemplate来显示验证错误信息。

<TextBox Text="{Binding Name}" Margin="5">
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={RelativeSource Self},
                                            Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

4.3 复杂数据绑定和集合视图

在处理复杂数据时,如数据集合的展示和筛选,WPF 提供了强大的支持。

  • 使用 ObservableCollection

ObservableCollection是一个动态数据集合,当集合中的元素发生添加、删除或修改时,会自动通知绑定的 UI 元素进行更新。

public class UserListViewModel : INotifyPropertyChanged
{
    private ObservableCollection<User> _users;

    public UserListViewModel()
    {
        _users = new ObservableCollection<User>
        {
            new User { Name = "Alice", Age = 25, Email = "alice@example.com" },
            new User { Name = "Bob", Age = 30, Email = "bob@example.com" }
        };
    }

    public ObservableCollection<User> Users
    {
        get { return _users; }
        set
        {
            _users = value;
            OnPropertyChanged(nameof(Users));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

CollectionViewSource可以用于对集合进行排序、筛选和分组。

<Window.Resources>
    <CollectionViewSource x:Key="UserViewSource" Source="{Binding Users}">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="Age" Direction="Ascending"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
</Window.Resources>
<ListView ItemsSource="{Binding Source={StaticResource UserViewSource}}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
            <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}"/>
            <GridViewColumn Header="Email" DisplayMemberBinding="{Binding Email}"/>
        </GridView>
    </ListView.View>
</ListView>

五、WPF MVVM 应用的最佳实践

5.1 分层架构

在构建大型应用时,采用分层架构可以进一步提高代码的可维护性和可扩展性。通常可以分为以下几层:

表示层(Presentation Layer) :包含 View 和 ViewModel,负责与用户进行交互和数据展示。

业务逻辑层(Business Logic Layer) :包含业务逻辑和规则,处理数据的验证、计算和业务流程。

数据访问层(Data Access Layer) :负责与数据库或其他数据源进行交互,实现数据的读取、写入和更新。

5.2 依赖注入

依赖注入是一种设计模式,它通过将对象的依赖关系外部化,使得代码更加灵活和可测试。在 WPF MVVM 应用中,可以使用依赖注入框架(如 Unity、Autofac 等)来管理对象的创建和依赖关系。

例如,使用 Unity 框架:

IUnityContainer container = new UnityContainer();
container.RegisterType<UserViewModel>();
container.RegisterType<UserService>();

UserViewModel viewModel = container.Resolve<UserViewModel>();

5.3 事件聚合器

在大型应用中,不同的 ViewModel 之间可能需要进行通信。事件聚合器是一种常用的解决方案,它允许 ViewModel 之间通过发布和订阅事件来进行通信,而不需要直接引用对方。

例如,使用 Prism 框架的EventAggregator:

public class MyEvent : PubSubEvent<string>
{
}

public class SenderViewModel
{
    private readonly IEventAggregator _eventAggregator;

    public SenderViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    public void SendMessage()
    {
        _eventAggregator.GetEvent<MyEvent>().Publish("Hello, Receiver!");
    }
}

public class ReceiverViewModel
{
    private readonly IEventAggregator _eventAggregator;

    public ReceiverViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
        _eventAggregator.GetEvent<MyEvent>().Subscribe(ReceiveMessage);
    }

    private void ReceiveMessage(string message)
    {
        MessageBox.Show(message);
    }
}

六、总结

通过本文的介绍,我们深入了解了 WPF 与 MVVM 设计模式的结合应用。WPF 提供了强大的图形界面开发能力,而 MVVM 模式则为构建可维护的大型应用架构提供了清晰的思路和规范。

结束语

展望未来,WPF 布局系统依然有着广阔的发展前景。随着硬件技术的不断革新,如高分辨率屏幕、折叠屏设备的日益普及,WPF 布局系统有望进一步强化其自适应能力,为用户带来更加流畅、一致的体验。在应对高分辨率屏幕时,能够更加智能地缩放和布局元素,确保文字清晰可读、图像不失真;对于折叠屏设备,可动态调整布局结构,充分利用多屏空间,实现无缝切换。

性能优化方面,微软及广大开发者社区将持续努力,进一步降低复杂布局的计算开销,提高布局更新的效率,使得 WPF 应用在处理大规模数据、动态界面时依然能够保持高效响应。通过改进算法、优化内存管理等手段,让 WPF 布局系统在性能上更上一层楼。

亲爱的朋友,无论前路如何漫长与崎岖,都请怀揣梦想的火种,因为在生活的广袤星空中,总有一颗属于你的璀璨星辰在熠熠生辉,静候你抵达。

愿你在这纷繁世间,能时常收获微小而确定的幸福,如春日微风轻拂面庞,所有的疲惫与烦恼都能被温柔以待,内心永远充盈着安宁与慰藉。

至此,文章已至尾声,而您的故事仍在续写,不知您对文中所叙有何独特见解?期待您在心中与我对话,开启思想的新交流。


————— 业精于勤,荒于嬉 —————

https://img-blog.csdnimg.cn/direct/e82d4f1cd63841b096def2d887fdf384.gif?#pic_center

————— 行成于思,毁于随 —————


优质源码分享


https://i-blog.csdnimg.cn/direct/832e221f2e4344619d7ef6d337d2ae40.gif#pic_center


💞 带你实现畅游前后端

🏰 带你体验酷炫大屏

💯 带你体验不一样得介绍

🎀 带你体验高大上得邀请


① 🉑提供云服务部署(有自己的阿里云);

② 🉑提供前端、后端、应用程序、H5、小程序、公众号等相关业务;

如🈶合作请联系我,期待您的联系。

:本文撰写于 CSDN平台 ,作者: xcLeigh所有权归作者所有) , ,如果相关下载没有跳转,请查看这个地址,相关链接没有跳转,皆是抄袭本文,转载请备注本文原地址。


亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏 ,如 🈶 问题请留言(评论),博主看见后一定及时给您答复,💌💌💌


原文地址: (防止抄袭,原文地址不可删除)