WPF入门到精通:3.MVVM简单应用及全局异常处理

这篇具有很好参考价值的文章主要介绍了WPF入门到精通:3.MVVM简单应用及全局异常处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

MVVM简介

在WPF应用程序开发中,MVVM(Model-View-ViewModel)是一种非常流行的架构模式。它为应用程序的设计提供了良好的分层结构和可扩展性。

结构分为下列三部分

  1. Model:定义了应用程序的数据模型 就是系统中的对象,可包含属性和行为(是一个class实体,是对现实中事物的抽象,开发过程中涉及到的事物都可以抽象为Model,例如用户的账号、密码、电话等),负责从数据源中获取数据并将其提供给ViewModel。

  2. ViewModel:封装了应用程序的业务逻辑,通过View类的DataContext属性绑定到View,负责将数据从Model传递到View,并将用户交互事件传递回Model。显示数据对应ViewMode中的Property,执行命令对应ViewModel中的Command。

  3. View:用xaml实现的界面,接收用户输入,把数据展现给用户,并与ViewModel交互以便进行数据绑定和命令绑定。

在MVVM模式中,ViewModel的主要职责是将数据从Model传递到View,并响应View的用户交互事件。ViewModel通过命令绑定和数据绑定与View进行交互。

MVVM优点

  1. 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  2. 灵活扩展:可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑;
  3. 易测试:可以针对ViewModel来写测试用例
  4. 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于xaml页面设计。

MVVM示例

以下是一个简单的WPF MVVM登录示例:

底层通用实体

ViewModelBase 

添加一个viewmodelbase方便后续数据双向绑定更新

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace YourProjectName.Comm
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void PC(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public void PCEH([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
CommandBase 

添加一个继承ICommand实体,方便后续绑定command

using System;
using System.Windows.Input;

namespace YourProjectName.Comm
{
    public class CommandBase : ICommand
    {
        private readonly Action<object> _execute;

        private readonly Func<object, bool> _canExecute;

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

        public CommandBase(Action<object> execute)
            : this(execute, null)
        {
        }

        public CommandBase(Action<object> execute, Func<object, bool> canExecute)
        {
            _execute = execute ?? throw new ArgumentNullException("execute");
            _canExecute = canExecute ?? ((Func<object, bool>)((object x) => true));
        }

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

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

        public void Refresh()
        {
            CommandManager.InvalidateRequerySuggested();
        }
    }
}
ViewModel及Model

在ViewModel文件夹下,创建一个名为LoginViewModel的类。 因为只有两个字段测试所以未新建Model,实际开发中注意新建

using System.Windows.Input;
using YourProjectName.Comm;


namespace YourProjectName.ViewModel 
{
    public class LoginViewModel : ViewModelBase 
    {
        private string _username;
        private string _password;
        private bool _rememberMe;

        public string Username 
        {
            get { return _username; }
            set { _username= value; PCEH();}
        }

        public string Password 
        {
            get { return _password; }
            set { _password= value; PCEH();}
        }

        public bool RememberMe 
        {
            get { return _rememberMe; }
                  set { _rememberMe= value; PCEH();}
        }

        public ICommand LoginCommand;

        private void Login() 
        {
   LoginCommand=  new CommandBase(async l =>
           {
            // TODO: Add login logic.
});
        }
    }
}
View

在View文件夹下,创建一个名为LoginView的XAML和CS文件。

<Window x:Class="YourProjectName.View.LoginView"
        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:YourProjectName.View"
        xmlns:vm="clr-namespace:YourProjectName.ViewModel"
        mc:Ignorable="d"
        Title="LoginView" Height="300" Width="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Label Grid.Row="0" Grid.Column="0" Content="Username:" />
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Username}" />
        <Label Grid.Row="1" Grid.Column="0" Content="Password:" />
        <PasswordBox Grid.Row="1" Grid.Column="1" Password="{Binding Password, UpdateSourceTrigger=PropertyChanged}" />
        <CheckBox Grid.Row="2" Grid.Column="1" Content="Remember me" IsChecked="{Binding RememberMe}" />
        <Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="Login" Command="{Binding LoginCommand}" />
        <TextBlock Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Text="Don't have an account? Sign up." />
    </Grid>
</Window>

初始化DataContext ,也可在页面中初始化

using System.Windows;

namespace YourProjectName.View 
{
    public partial class LoginView : Window 
    {
   private readonly LoginViewModel model;
        public LoginView() 
        {
            InitializeComponent();
      DataContext = model = new();
        }
    }
}

启动应用程序并测试登录页面。在“TODO”注释的位置添加实际的登录代码。

全局异常处理

在WPF应用程序中,全局异常处理非常重要。全局异常处理可以帮助我们捕获应用程序中的所有未处理异常,防止程序异常崩溃并提供更好的用户体验。在WPF中,可以通过在应用程序的App.xaml.cs文件中添加以下代码来实现全局异常处理:

异常处理示例

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        DispatcherUnhandledException += App_DispatcherUnhandledException;
       TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
    }

    private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
    {
        //处理UI线程上的未处理异常
        e.Handled = true;
        MessageBox.Show("发生错误:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
    }

    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        //处理非UI线程上的未处理异常
        Exception ex = (Exception)e.ExceptionObject;
        MessageBox.Show("发生错误:" + ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
    }

  /// <summary>
        /// Task线程内未捕获异常处理事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs ex)
        {
 MessageBox.Show("Task线程异常:" + ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            //设置该异常已察觉(这样处理后就不会引起程序崩溃)
            e.SetObserved();
        }
}

以上代码会在应用程序启动时为当前域的未处理异常事件和UI线程上的未处理异常事件及task线程异常注册处理程序。在发生异常时,会弹出一个消息框来通知用户并不会造成程序崩溃。

总结:

MVVM模式是WPF应用程序开发中非常重要的主题。通过理解和实战练习,我们可以更好地开发出强大和稳定的应用程序。

全局异常处理是程序中必不可少的一步,能保障程序在异常发生过程中正常运行。文章来源地址https://www.toymoban.com/news/detail-669281.html

到了这里,关于WPF入门到精通:3.MVVM简单应用及全局异常处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(8) -- 使用Converter类实现内容的转义处理

    在我们WPF应用端的时候,和WInform开发或者Vue前端开发一样,有时候也需要对内容进行转义处理,如把一些0,1数值转换为具体含义的文本信息,或者把一些布尔变量转换为是否等,都是常见的转换处理,本篇随笔介绍在WPF应用端对内容使用Converter类实现内容的转义处理的操作。

    2024年02月08日
    浏览(48)
  • 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(6) -- 窗口控件脏数据状态IsDirty的跟踪处理

    在我们窗口新增、编辑状态下的时候,我们往往会根据是否修改过的痕迹-也就是脏数据状态进行跟踪,如果用户发生了数据修改,我们在用户退出窗口的时候,提供用户是否丢弃修改还是继续编辑,这样在一些重要录入时的时候,可以避免用户不小心关掉窗口,导致窗口的数

    2024年02月08日
    浏览(54)
  • C# WPF简单的MVVM模式事例

    WPF中使用MVVM模式开发有诸如以下优点: 1.结构清晰明朗,上手成本低,一个新人也能快速的定位自己需要改动代码的位置。 2.耦合度低,更改WPF控件不影响数据结构,更改代码成本低。 3.可重用性高,比如一个处理逻辑放到ViewModel模块中,其他界面如果要用掉直接调用即可。

    2024年02月09日
    浏览(49)
  • WPF 项目中 MVVM模式 的简单例子说明

    MVVM 是 Model view viewModel 的简写。MVVM模式有助于将应用程序的业务和表示逻辑与用户界面清晰分离。 几个概念的说明: model :数据,界面中需要的数据,最好不要加逻辑代码 view : 视图就是用户看到的UI结构 xaml 文件 viewModel : 业务逻辑代码 绑定器:声明性数据和命令绑定隐含在

    2024年02月11日
    浏览(32)
  • WPF 入门笔记 - 07 - MVVM示例

    滴咚,大家好久不见💖。好就没写东西了,鸽着鸽着就无了😭。。。 回到正题,上篇文章说完命令提了一嘴 MVVM 模式直接就上 MVVMLight 这些程序的框架了,虽然也没说多少,但还是有点不好过渡,这篇对 MVVM 做一些系统学习,同时复习一下前几篇博文中的内容,完成一个采

    2024年02月13日
    浏览(52)
  • WPF入门到跪下 第九章 MVVM-跨模块交互

    在实际开发过程中,经常会遇到多个窗口对象,随之而来的就是对应的多个ViewModel对象,这些对象在一定条件下会发生相互访问的情况,例如VM与不同窗口交互、VM与不同VM交互,这些不同模块对象之间的交互,就是跨模块交互。 MVVM模式下跨模块交互解决方案 面对跨模块交互

    2024年02月02日
    浏览(35)
  • WPF如何构建MVVM+模块化的桌面应用

    模块化是一种分治思想,不仅可以分离复杂的业务逻辑,还可以进行不同任务的分工。模块与模块之间相互独立,从而构建一种松耦合的应用程序,便于开发和维护。 .NET 6 + WPF + Prism (v8.0.0.1909) + HandyControl (v3.4.0) 什么是MVVM Model-View-ViewModel  是一种软件架构设计,它是一种简化

    2024年02月13日
    浏览(44)
  • WPF入门教程系列二十九 ——DataGrid使用示例MVVM模式(7)

    WPF入门教程系列目录 WPF入门教程系列二——Application介绍 WPF入门教程系列三——Application介绍(续) WPF入门教程系列四——Dispatcher介绍 WPF入门教程系列五——Window 介绍 WPF入门教程系列十一——依赖属性(一) WPF入门教程系列十五——WPF中的数据绑定(一)   接上文 WPF入门教程

    2024年02月10日
    浏览(46)
  • WPF入门教程系列二十八 ——DataGrid使用示例MVVM模式(6)

    WPF入门教程系列目录 WPF入门教程系列二——Application介绍 WPF入门教程系列三——Application介绍(续) WPF入门教程系列四——Dispatcher介绍 WPF入门教程系列五——Window 介绍 WPF入门教程系列十一——依赖属性(一) WPF入门教程系列十五——WPF中的数据绑定(一)       7.上面Buttom的

    2024年02月09日
    浏览(39)
  • WPF入门教程系列二十八 ——DataGrid使用示例MVVM模式(5)

    WPF入门教程系列目录 WPF入门教程系列二——Application介绍 WPF入门教程系列三——Application介绍(续) WPF入门教程系列四——Dispatcher介绍 WPF入门教程系列五——Window 介绍 WPF入门教程系列十一——依赖属性(一) WPF入门教程系列十五——WPF中的数据绑定(一)           通过上面

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包