企业应用开发 WPF MVVM项目模板_第1页
企业应用开发 WPF MVVM项目模板_第2页
企业应用开发 WPF MVVM项目模板_第3页
企业应用开发 WPF MVVM项目模板_第4页
企业应用开发 WPF MVVM项目模板_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

企业应用开发WPFMVVM项目模板一、推荐技术栈基础框架:.NET8或.NET9MVVM框架:CommunityToolkit.Mvvm

(基于源生成器,零样板代码)依赖注入:Microsoft.Extensions.DependencyInjectionUI组件库:MaterialDesignInXamlToolkit

HandyControl

(提供企业级统一外观)ORM/数据库:EFCore

(配合SQLServer/PostgreSQL)日志记录:Serilog配置管理:Microsoft.Extensions.Options二、标准解决方案目录结构建议按照按功能分层而不是按类型分层(不要建ViewModels、Views、Models三个大杂烩文件夹,这在企业级项目中后期极其痛苦)。MyEnterpriseApp.Wpf/├──Assets/#静态资源(图片、字体、全局字典)├──Controls/#项目内自定义的通用控件├──Core/#核心基础设施(不包含具体业务)│├──App.xaml.cs#DI容器配置、全局异常接管、启动入口│├──Mvvm/#ViewModel基类扩展(如果Toolkit不够用)│├──Services/#基础服务接口与实现(如导航服务、对话框服务、文件选择服务)│└──Events/#全局消息事件定义├──Modules/#业务模块(按业务领域划分)│├──Login/││├──Views/│││└──LoginView.xaml││├──ViewModels/│││└──LoginViewModel.cs││└──Models/#纯粹的数据结构(DTO)│├──Dashboard/│└──UserManagement/├──Services/#业务服务层(调用API或数据库)│├──IUserService.cs│└──UserService.cs├──Converters/#全局值转换器├──Styles/#全局样式├──App.xaml#合并资源字典└──MainWindow.xaml#壳窗口(仅包含导航区域或ContentControl)三、核心基类与代码实现1.ViewModel基类(利用源生成器)不需要手写

INotifyPropertyChanged,使用

[ObservableProperty]

即可。usingCommunityToolkit.Mvvm.ComponentModel;usingCommunityToolkit.Mvvm.Messaging;namespaceMyEnterpriseApp.Core.Mvvm;//继承ObservableObject,可选继承IRecipient<T>接收全局消息publicabstractclassViewModelBase:ObservableObject,IRecipient<ErrorMessage>{privatestring?_title;publicstring?Title{get=>_title;set=>SetProperty(ref_title,value);}//可选:在ViewModel创建时注册消息publicViewModelBase(){WeakReferenceMessenger.Default.Register<ErrorMessage>(this);}//接收并处理全局错误消息(例如在底层Service抛出异常时发送到UI显示)publicvoidReceive(ErrorMessagemessage){//在此处触发统一的UI提示,例如绑定到界面的错误提示条Title=$"错误:{message.Value}";}}//定义消息类型publicrecordErrorMessage(stringValue);2.业务ViewModel示例(以用户管理为例)注意使用

[RelayCommand]

自动生成命令。usingCommunityToolkit.Mvvm.ComponentModel;usingCommunityToolkit.Mvvm.Input;usingMyEnterpriseApp.Services;namespaceMyEnterpriseApp.Modules.UserManagement.ViewModels;publicpartialclassUserListViewModel:ViewModelBase{privatereadonlyIUserService_userService;publicUserListViewModel(IUserServiceuserService){_userService=userService;Title="用户列表";}[ObservableProperty]privatestring_searchKeyword=string.Empty;[ObservableProperty]privateIEnumerable<UserDto>_users=Enumerable.Empty<UserDto>();[RelayCommand]privateasyncTaskLoadDataAsync(){try{Users=await_userService.GetUsersAsync(SearchKeyword);}catch(Exceptionex){//发送全局异常消息,而不是直接MessageBoxWeakReferenceMessenger.Default.Send(newErrorMessage(ex.Message));}}//源生成器会自动生成privateRelayCommandAddUserCommand=>new(async()=>{...});[RelayCommand]privateasyncTaskAddUserAsync(){//导航逻辑由服务处理//_navigationService.NavigateTo<AddUserViewModel>();}}四、基础设施:导航与对话框企业级应用绝对不能在ViewModel里

newMainWindow()。必须抽象出导航和对话框服务。1.导航服务接口与实现//接口(放在Core/Services)publicinterfaceINavigationService{voidNavigateTo<TViewModel>()whereTViewModel:ViewModelBase;}//实现publicclassNavigationService:INavigationService{privatereadonlyIServiceProvider_serviceProvider;//假设主窗口有一个名为"MainContent"的ContentControlprivatereadonlyFunc<object,Type,bool>_viewResolver;publicNavigationService(IServiceProviderserviceProvider,Func<object,Type,bool>viewResolver){_serviceProvider=serviceProvider;_viewResolver=viewResolver;}publicvoidNavigateTo<TViewModel>()whereTViewModel:ViewModelBase{//从DI容器获取ViewModel实例(自动注入构造函数依赖)varviewModel=_serviceProvider.GetRequiredService<TViewModel>();//根据约定找到对应的View(例如UserListViewModel->UserListView)varviewType=Type.GetType($"MyEnterpriseApp.Modules.{GetModuleName<TViewModel>()}.Views.{GetViewName<TViewModel>()}View");if(viewType!=null){varview=(FrameworkElement)Activator.CreateInstance(viewType);view.DataContext=viewModel;//绑定上下文//更改主窗口的Content_viewResolver(view,viewType);}}}2.对话框服务(代替MessageBox)publicinterfaceIDialogService{Task<bool>ShowConfirmAsync(stringtitle,stringmessage);voidShowError(stringmessage);}//配合MaterialDesignInXamlToolkit的DialogHost实现此接口,实现完全解耦。五、启动与依赖注入这是企业级应用的大脑,在

App.xaml.cs

中统一编排。注意:必须去掉

App.xaml

中的

StartupUri="MainWindow.xaml"。usingMicrosoft.Extensions.DependencyInjection;usingMicrosoft.Extensions.Hosting;usingSystem.Windows;namespaceMyEnterpriseApp.Core;publicpartialclassApp:Application{privateIHost?_host;publicApp(){//全局未捕获异常处理(企业级必备)DispatcherUnhandledException+=App_DispatcherUnhandledException;AppDomain.CurrentDomain.UnhandledException+=CurrentDomain_UnhandledException;TaskScheduler.UnobservedTaskException+=TaskScheduler_UnobservedTaskException;}protectedoverrideasyncvoidOnStartup(StartupEventArgse){base.OnStartup(e);_host=Host.CreateDefaultBuilder(e.Args).ConfigureServices((context,services)=>{//1.注册基础设施服务services.AddSingleton<INavigationService,NavigationService>();services.AddSingleton<IDialogService,DialogService>();//2.注册业务服务services.AddTransient<IUserService,UserService>();//3.注册ViewModel(Transient或Scoped)services.AddTransient<Modules.Login.ViewModels.LoginViewModel>();services.AddTransient<Modules.UserManagement.ViewModels.UserListViewModel>();//4.注册主窗口(Shell)services.AddSingleton<MainWindow>();}).Build();await_host.StartAsync();//解析并显示主窗口varmainWindow=_host.Services.GetRequiredService<MainWindow>();mainWindow.Show();}protectedoverrideasyncvoidOnExit(ExitEventArgse){if(_hostisnotnull){await_host.StopAsync();_host.Dispose();}base.OnExit(e);}//全局异常捕获,写入Serilog日志并优雅提示privatevoidApp_DispatcherUnhandledException(objectsender,System.Windows.Threading.DispatcherUnhandledExceptionEventArgse){//Log.Error(e.Exception,"发生未处理的UI线程异常");e.Handled=true;//防止程序崩溃//MessageBox.Show("系统发生未知错误,请联系管理员。");}//...其他异常捕获方法类似}六、View层的约束(XAML)企业级XAML必须严格遵守规则:Code-Behind必须为空:除了必要的View级别动画或必须拖拽的事件(如DragOver,即便如此也要通过

x:Bind

或CallMethodAction转发给ViewModel),.xaml.cs

里不应该有任何业务逻辑。使用资源字典统一风格:按钮长什么样、输入框长什么样,全局定义,绝不每个界面自己写。DataTemplate映射:在

App.xaml

中利用

DataTemplate

自动将ViewModel映射到View(这是比手动解析类型更优雅的导航方式):无效的SVG格式*采用这种DataTemplat

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论