找回密码
 立即注册
首页 业界区 业界 WPF治具软件模板分享

WPF治具软件模板分享

左丘纨 2025-9-21 21:29:50
目录

  • WPF治具软件模板分享

    • 程序功能介绍
    • 功能实现

      • 导航功能
      • 程序配置
      • 日志功能

    • 界面介绍


WPF治具软件模板分享

运行环境:VS2022   .NET 8.0
完整项目:Gitee仓库
项目重命名方法参考:网页
概要:针对治具单机软件制作了一个设计模板,此项目可对一些治具的PC简易软件项目提供一个软件模板,可以通过修改项目名快速开发,本项目使用了CommunityToolkit.Mvvm来搭建MVVM框架,使用了Microsoft.Extensions.DependencyInjection来实现DI依赖注入实现IOC,并使用了WPFUI作为UI框架 这个项目可以通过重命名修改成自己所需的软件项目,实现减少重复创建框架的目的 此项目还有很多不足,望大家多多谅解!
程序功能介绍

此程序适用于治具的PC简易软件的快速开发,软件各个功能实现如下:
MVVM框架:CommunityToolkit.Mvvm库
DI依赖注入:Microsoft.Extensions.DependencyInjection
UI框架:WPFUI库
程序日志:NLog库
程序配置:System.Text.Json库
多语言支持:resx资源文件+WPFLocalizeExtension库
软件文件架构如下图所示
1.png

功能实现

导航功能


  • App.xaml.cs
  1. var container = new ServiceCollection();
  2. //...
  3. //注册导航服务
  4. container.AddSingleton<Common.Services.NavigationService>();
  5. //...
  6. Services = container.BuildServiceProvider();
复制代码

  • MainWindow.xaml
  1. <Grid>
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="50"/>
  4.         <RowDefinition/>
  5.     </Grid.RowDefinitions>
  6.     <Grid>
  7.         <ui:TitleBar Title="JIG_SoftTemplate_V1.0.0" Background="#e5e5e5">
  8.             <ui:TitleBar.Icon>
  9.                 <ui:ImageIcon Source="/Resources/Image/Company_logo.png"/>
  10.             </ui:TitleBar.Icon>
  11.         </ui:TitleBar>
  12.     </Grid>
  13.     <Grid Grid.Row="1" x:Name="ShowGrid">
  14.         <Frame x:Name="rootFrame"/>
  15.         <ui:SnackbarPresenter x:Name="rootSnackbarPresenter" Margin="0,0,0,-15"/>
  16.         <ContentPresenter x:Name="rootContentDialog"/>
  17.     </Grid>
  18. </Grid>
复制代码

  • MainWindow.xaml.cs
  1. public partial class MainWindow
  2. {
  3.     public MainWindow(MainWindowViewModel viewModel, Common.Services.NavigationService navigationService)
  4.     {
  5.         InitializeComponent();
  6.         DataContext = viewModel;
  7.         navigationService.SetMainFrame(rootFrame);
  8.         App.Current.Services.GetRequiredService<ISnackbarService>().SetSnackbarPresenter(rootSnackbarPresenter);
  9.         App.Current.Services.GetRequiredService<IContentDialogService>().SetDialogHost(rootContentDialog);
  10.     }
  11. }
复制代码

  • NavigationService.cs
  1. public class NavigationService
  2. {
  3.     private Frame? mainFrame;
  4.     public void SetMainFrame(Frame frame) => mainFrame = frame;
  5.     private Type? FindView<VM>()
  6.     {
  7.         return Assembly
  8.             .GetAssembly(typeof(VM))
  9.             ?.GetTypes()
  10.             .FirstOrDefault(t => t.Name == typeof(VM).Name.Replace("ViewModel", ""));
  11.     }
  12.     public void Navigate<VM>()
  13.         where VM : ViewModelBase
  14.     {
  15.         Navigate<VM>(null);
  16.     }
  17.     public void Navigate<VM>(Dictionary<string, object?>? extraData)
  18.         where VM : ViewModelBase
  19.     {
  20.         var viewType = FindView<VM>();
  21.         if (viewType is null)
  22.             return;
  23.         var page = App.Current.Services.GetService(viewType) as Page;
  24.         mainFrame?.Navigate(page, extraData);
  25.     }
  26. }
复制代码
在MainWindow.xaml里放Frame控件,在MainWindow.xaml.cs里,调用NavigationService的SetMainFrame方法设定了Frame组件实例,然后在VM中调用Navigate方法即可跳转页面,示例:navigationService.Navigate();
需注意,View和ViewModel需要名称对的上,如NavigationService.cs中所示,比如HomePage.xaml的ViewModel就是HomePageViewModel,名称错误的话,会在FindView方法中报错
程序配置


  • App.xaml.cs
  1. var container = new ServiceCollection();
  2. //...
  3. //注册Json配置文件服务
  4. container.AddSingleton<Common.Services.JsonConfigService>();
  5. //...
  6. Services = container.BuildServiceProvider();
复制代码

  • AppConfigModel.cs
  1. public class AppConfigModel
  2. {
  3.     public CommonConfig? Common {  get; set; }
  4.     public JIGCommConfig? JIGComm { get; set; }
  5. }
  6. public class CommonConfig
  7. {
  8.     public string? DataStoragePath { get; set; }
  9.     public string? SelectedLang { get; set; }
  10. }
  11. public class JIGCommConfig
  12. {
  13. }
复制代码

  • JsonConfigService.cs
  1. public class JsonConfigService
  2. {
  3.     private const string ConfigFileName = "AppSettings.json";
  4.     private readonly LoggerService loggerService;
  5.     public JsonConfigService(LoggerService loggerService)
  6.     {
  7.         this.loggerService = loggerService;
  8.     }
  9.     public async Task<T> LoadConfigAsync<T>(T defaultValue = default) where T : new()
  10.     {
  11.         try
  12.         {
  13.             var filePath = GetConfigFilePath();
  14.             if (!File.Exists(filePath))
  15.             {
  16.                 loggerService.Info("配置文件不存在,返回默认值");
  17.                 await SaveConfigAsync(defaultValue ?? new T());
  18.                 return defaultValue ?? new T();
  19.             }
  20.             await using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  21.             return await JsonSerializer.DeserializeAsync<T>(fs) ?? new T();
  22.         }
  23.         catch (Exception ex)
  24.         {
  25.             loggerService.Error("加载配置文件失败", ex);
  26.             return defaultValue ?? new T();
  27.         }
  28.     }
  29.     public async Task SaveConfigAsync<T>(T config)
  30.     {
  31.         try
  32.         {
  33.             var filePath = GetConfigFilePath();
  34.             var dirPath = Path.GetDirectoryName(filePath);
  35.             if (!Directory.Exists(dirPath))
  36.             {
  37.                 Directory.CreateDirectory(dirPath);
  38.             }
  39.             var options = new JsonSerializerOptions
  40.             {
  41.                 WriteIndented = true,
  42.                 Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
  43.             };
  44.             await using var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
  45.             await JsonSerializer.SerializeAsync(fs, config, options);
  46.             loggerService.Info("配置文件保存成功");
  47.         }
  48.         catch (Exception ex)
  49.         {
  50.             loggerService.Error("保存配置文件失败", ex);
  51.             throw;
  52.         }
  53.     }
  54.     private static string GetConfigFilePath()
  55.     {
  56.         // 使用程序根目录存储配置文件
  57.         return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFileName);
  58.     }
  59. }
复制代码
调用服务时,只需调用LoadConfigAsync和SaveConfigAsync异步方法即可,示例如下:
  1. //读取配置文件
  2. string DataStoragePath = "";
  3. var loadedConfig = await jsonConfigService.LoadConfigAsync(new AppConfigModel());
  4. if (loadedConfig != null)
  5. {
  6.     if (loadedConfig?.Common != null)
  7.     {
  8.         //更新到属性
  9.         DataStoragePath = loadedConfig.Common.DataStoragePath;
  10.     }
  11. }
  12. //保存配置到文件
  13. private AppConfigModel appConfig;
  14. //初始化appConfig
  15. appConfig = new AppConfigModel();
  16. appConfig.Common = new CommonConfig();
  17. //更新界面上数据到配置appConfig中
  18. appConfig.Common.DataStoragePath = DataStoragePath;
  19. //保存配置
  20. await jsonConfigService.SaveConfigAsync(appConfig);
复制代码
日志功能


  • App.xaml.cs
  1. var container = new ServiceCollection();
  2. //...
  3. //注册日志服务
  4. container.AddSingleton<Common.Services.LoggerService>();
  5. //...
  6. Services = container.BuildServiceProvider();
复制代码

  • NLog.config
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.       autoReload="true">
  5.         <targets>
  6.                
  7.                 <target name="InfoFile"
  8.                                 xsi:type="File"
  9.                                 fileName="LogFile/LogInfo/${shortdate}-Info.log"
  10.                                 layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff} [INFO] ${message}${newline}"
  11.                                 encoding="UTF-8"
  12.                                 archiveEvery="Day"
  13.                                 maxArchiveFiles="100"
  14.                                 concurrentWrites="true"
  15.                                 keepFileOpen="false"/>
  16.                
  17.                 <target name="ErrorFile"
  18.                                 xsi:type="File"
  19.                                 fileName="LogFile/LogError/${shortdate}-Error.log"
  20.                                 layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff} [ERROR] [ThreadID:${threadid}] ${message}${newline}[StackTrace:${exception:format=Message}]${newline}"
  21.                                 encoding="UTF-8"
  22.                                 archiveEvery="Day"
  23.                                 maxArchiveFiles="100"
  24.                                 concurrentWrites="true"
  25.                                 keepFileOpen="false"/>
  26.         </targets>
  27.         <rules>
  28.                
  29.                 <logger name="MyLog" minlevel="Info" maxlevel="Info" writeTo="InfoFile" final="true" />
  30.                 <logger name="MyLog" minlevel="Error" maxlevel="Error" writeTo="ErrorFile" final="true" />
  31.         </rules>
  32. </nlog>
复制代码

  • LoggerService.cs
  1. public class LoggerService
  2. {
  3.     private static readonly NLog.ILogger Logger = NLog.LogManager.GetLogger("MyLog");
  4.     public void Info(string message)
  5.     {
  6.         Logger.Info(message);
  7.     }
  8.     public void Error(string message, Exception? ex = null)
  9.     {
  10.         Logger.Error(ex, message);
  11.     }
  12. }
复制代码
调用服务时,只需调用Info和Error方法即可,示例如下:
  1. private void FunA()
  2. {
  3.     try
  4.     {
  5.         loggerService.Info("程序成功");
  6.     }
  7.     catch (Exception ex)
  8.     {
  9.         loggerService.Error("程序出错", ex);
  10.     }
  11. }
复制代码
界面介绍

各个界面如下图所示
主界面
2.png

登录界面
3.png

设置界面
4.png

具体项目请自行到Gitee仓库查看吧

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册