描述

当我们安装完 DotNetCore 3.0 版本的 SDK 后,我们就可以创建基于 DotNetCore 的 WPF 项目模板,通过如下 CLI 可以方便快捷的创建并运行我们的项目:

Copy

dotnet new wpf -n WpfApp
cd WpfApp
dotnet restore
dotnet run

做过 WPF 开发的朋友都知道,这个项目模板肯定不符合我们的预期,我们希望我们的项目模板能够加入 MVVM 的默认代码段,并且能够和 DotNetCore 紧密合作,这样岂不是更加方便了吗? 所以本文使用 MVVM 的一种实现 MvvmLightStd10 来教大家如何创建一个我们理想的项目模板。

操作

首先,我们基于 DotNetCore 3.0 创建一个原始的 WPF 项目模板,然后引用如下库:

  • Microsoft.Extensions.DependencyInjection

  • MvvmLightLibsStd10

可通过执行 cli 命令进行安装

Copy

dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package MvvmLightLibsStd10

注:因为我们使用了 DotNetCore,所以我们尽量让我们安装的第三方包是基于 .NET Standard 方式来实现。

然后,尝试修改我们的这个项目,把它改成我们以后期望创建的项目模板的样子。可以参考我的如下修改:

项目结构如下图所示:

其中,src\Models\DataItem.cs 的示例代码如下所示:

Copy

using System;
using System.Collections.Generic;
using System.Text;

namespace WpfApp.Models
{
public class DataItem
{
public string Title { get; private set; }

public DataItem(string title)
{
Title = title;
}
}
}

src\Models\IDataService.cs 的示例代码如下所示:

Copy

using System;
using System.Collections.Generic;
using System.Text;

namespace WpfApp.Models
{
public interface IDataService
{
void GetData(Action<DataItem, Exception> callback);
}
}

src\Models\DataService.cs 的示例代码如下所示:

Copy

using System;
using System.Collections.Generic;
using System.Text;

namespace WpfApp.Models
{
public class DataService : IDataService
{
public void GetData(Action<DataItem, Exception> callback)
{
var item = new DataItem("Hello .NET Core!");
callback(item, null);
}
}
}

src\ViewModels\MainViewModel.cs 的示例代码如下所示:

Copy

using GalaSoft.MvvmLight;
using WpfApp.Models;

namespace WpfApp.ViewModels
{
public class MainViewModel : ViewModelBase
{
private readonly IDataService _dataService;

private string _welcomeTitle;
public string WelcomeTitle
{
get { return _welcomeTitle; }
set { Set(ref _welcomeTitle, value); }
}

public MainViewModel(IDataService dataService)
{
_dataService = dataService;
_dataService.GetData(
(item, error) =>
{
if (error != null)
{
return;
}

WelcomeTitle = item.Title;
});
}
}
}

src\Views\MainView.xaml 的示例代码如下所示:

Copy

<Window
x:Class="WpfApp.Views.MainView"
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:local="clr-namespace:WpfApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Grid>
<Label
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding WelcomeTitle}"
FontSize="40" />
</Grid>
</Window>

src\Views\MainView.xaml.cs 的示例代码如下所示:

Copy

using System.Windows;
using WpfApp.ViewModels;

namespace WpfApp.Views
{
public partial class MainView : Window
{
public MainView(MainViewModel vm)
{
InitializeComponent();
this.DataContext = vm;
}
}
}

src\App.xaml 的示例代码如下所示:

Copy

<Application
x:Class="WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp" />

src\App.xaml.cs 的示例代码如下所示:

Copy

using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using WpfApp.Models;
using WpfApp.ViewModels;
using WpfApp.Views;

namespace WpfApp
{
public partial class App : Application
{
public ServiceProvider ServiceProvider { get; private set; }

protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);

ServiceProvider = serviceCollection.BuildServiceProvider();

var mainWindow = ServiceProvider.GetRequiredService<MainView>();
mainWindow.Show();
}

private void ConfigureServices(ServiceCollection services)
{
services.AddTransient<MainView>();
services.AddTransient<MainViewModel>();

services.AddScoped<IDataService, DataService>();
}
}
}

修改完毕后尝试编译运行我们的项目,确保可以正常编译运行。

之后,在我们的项目根目录 src 下新建一个 .template.config 文件夹,然后在里面新建一个 template.json文件,进行如下示例配置:

Copy

{
"$schema": "http://json.schemastore.org/template",
"author": "hippiezhou <hippiezhou@outlook.com>",
"classifications": ["wpf", "mvvmlight", "Dependency Injection"],
"name": "wpf mvvmlight: use dotnetcore to create wpf with mvvmlight.",
"tags": {
"language": "C#",
"type": "project"
},
"identity": "wpf.mvvmlight",
"shortName": "wpf-mvvmlight",
"sourceName": "wpf.mvvmlight",
"preferNameDirectory": true
}

最后,打开我们的终端,将目录切换至当前项目目录下(就是 .template.config 所在的目录),然后执行下述安装操作

Copy

dotnet new -i C:\Users\hippieZhou\Desktop\helloworld\wpfapp

此时,我们的项目模板会被打包到 DotNetCore 的 CLI 中,如下图所示:

同时,在 C:\Users\hippieZhou.templateengine\dotnetcli\v3.0.100-preview3-010431 目录下的以 templatecache.json 结尾的 JSON 文件内容也会发生修改,会在 TemplateInfo 结点下新增一个如下的节点内容:

Copy

{
"ConfigMountPointId": "f3861181-7a43-4fc5-ab1c-12d95e734c0a",
"Author": "hippiezhou <hippiezhou@outlook.com>",
"Classifications": [
"wpf",
"mvvmlight",
"Dependency Injection"
],
"DefaultName": null,
"Description": "",
"Identity": "wpf.mvvmlight",
"GeneratorId": "0c434df7-e2cb-4dee-b216-d7c58c8eb4b3",
"GroupIdentity": "",
"Precedence": 0,
"Name": "wpf mvvmlight: use dotnetcore to create wpf with mvvmlight.",
"ShortNameList": [
"wpf-mvvmlight"
],
"Tags": {
"language": {
"Description": null,
"ChoicesAndDescriptions": {
"C#": ""
},
"DefaultValue": "C#"
},
"type": {
"Description": null,
"ChoicesAndDescriptions": {
"project": ""
},
"DefaultValue": "project"
}
},
"CacheParameters": {
"name": {
"DataType": "string",
"DefaultValue": null,
"Description": "The default name symbol"
}
},
"ConfigPlace": "/.template.config/template.json",
"LocaleConfigMountPointId": "00000000-0000-0000-0000-000000000000",
"LocaleConfigPlace": null,
"HostConfigMountPointId": "00000000-0000-0000-0000-000000000000",
"HostConfigPlace": null,
"ThirdPartyNotices": null,
"BaselineInfo": {},
"HasScriptRunningPostActions": false,
"ConfigTimestampUtc": null
},

注:如果后期我们不慎将我们的模板删除了,我们通过删除掉这两个文件里面对应的模板节点就可以在 CLI 中取消应用了。

我们可以使用下述操作进行测试一下:

Copy


dotnet new wpf-mvvmlight -n test

cd test

dotnet restore

dotnet run

如果不出意外的话,我们就可以看到这个项目的代码段和我们自定义的模板代码段是一样的。

如果卸载我们的项目模板可以使用如下命令:

Copy

dotnet new -u C:\Users\hippieZhou\Desktop\helloworld\wpfapp

注:我们需要确保我们的自定义模板不能丢失,要不然到时候就卸载就麻烦了(至少目前看来是这样的)。

关于如何将我们的自定义模板可以上传到 NuGet 供别人下载使用,这里就不做介绍了,具体操作可参考园里介绍如何在 DotNetCore MVC 中打造自己的项目模板方法是一样的。我在本文中的创建的代码模板也不会提交上去,还是等着 MVVMLight 的原作者 Laurent Bugnion 来操刀会好一些。

总结

本文介绍了如何通过 DotNet CLI 来创建自定义的 WPF 项目模板。在实际的使用过程中,CLI 的功能和支持的参数会更多,所以感兴趣的朋友可以自行研究。

相关参考

  • how-to-create-a-dot-net-new-project-template-in-dot-net-core

  • 打造自己的.NET Core项目模板

使用 DotNet CLI 创建自定义的 WPF 项目模板相关推荐

  1. VS2017 创建自定义WPF项目模板

    注意:本文主要是介绍建立WPF程序的模板,其他类型的模板并不确定以此方式创建有么有没问题 1.首先确保你的Visual Studio 已安装Visual Studio SDK 这个组件,如果安装的时候 ...

  2. 使用 Vue CLI 创建 Vue 2.x 项目

    使用 Vue CLI 创建 Vue 2.x 项目 什么是 Vue CLI 使用 Vue CLI 创建 Vue.js 项目 1. 准备 Node 和 npm 1.1 检查 Node 版本: 1.2 检查 ...

  3. 使用.Net Core CLI命令dotnet new创建自定义模板

    文章起源来自一篇博客:使用 .NET CORE 创建 项目模板,模板项目,Template - DeepThought - 博客园 之前使用Abp的时候就很认同Abp创建模板项目的方式.想不到.Net ...

  4. Excel-VBA基础(17):创建自定义函数并存为模板调用示例

    需求 日常工作中经常用到比Excel内置函数复杂的数据计算,而且使用频率非常高,有时候可以通过增加过渡数据,利用内置函数而解决,但有时候通过内置函数解决不了.此时可以用自定义函数的方法解决. 解决方案 ...

  5. 自定义vue-cli生成项目模板配置(1)

    最近在读<变量>,目前得到的认知之一:慢变量才是决定事物长期发展的因素. 打算自定义vue-cli的脚手架或者根据自己的需要设置项目模板的相关参数,很大程度与慢变量这个概念相关. 当然,我 ...

  6. dotNET中创建自定义的配置节

    自定义节的配置文件 myCustom.config 如下: <?xml version="1.0" encoding="utf-8"?> <c ...

  7. 使用 .NET Core模板引擎创建自定义的模板和项目

    本文要点 .NET CLI 包含了一个模板引擎,它可以直接利用命令行创建新项目和项目项.这就是"dotnet new"命令. 默认模板集涵盖了默认控制台和基于 ASP.NET 的应 ...

  8. 【Maven实战技巧】「插件使用专题」Maven-Archetype插件创建自定义maven项目骨架

    技术推荐 自定义Archetype Maven骨架/以当前项目为模板创建maven骨架,可以参考http://maven.apache.org/archetype/maven-archetype-pl ...

  9. 使用dotnet Cli向nuget发布包

    长话短说, 今天分享如何在nuget.org创建并发布.NET Standard package. 前置 安装勾选.NET Core开发套件的Visual Studio; 安装dotnet Cli 从 ...

最新文章

  1. 清理mysql创建的游戏_Linux定时清理游戏log及mysql定时任务删除游戏日志数据的步骤...
  2. 目前电子计算机已经发展到,目前电子计算机已经发展到什么计算机?
  3. config database.php,CodeIgniter配置之database.php用法实例分析
  4. 函数求值需要运行所有线程_精读《深度学习 - 函数式之美》
  5. php css布局技巧,最全的CSS开发常用技巧
  6. linux下 udf提权_mysql——udf提权
  7. dbms数据库管理系统_数据库管理系统(DBMS)中的视图
  8. (4)css2.1选择器
  9. [转]SQL中的case when then else end用法
  10. 云资源中的低成本战斗机——竞价实例,AWS、阿里云等六家云厂商完全用户使用指南
  11. 火山引擎张鑫解读云原生2021:K8s 开先河、技能全栈、业务“无感”
  12. CSS子元素居中(父元素宽高已知,子元素未知)
  13. 2.5.5.2 特殊文件:/dev/null 与 /dev/tty
  14. 应邀参加51CTO专家座谈门诊——驱动开发技术探析【2008.11.20在线】
  15. 批量执行newman
  16. GBK汉字的索引方法
  17. 多功能jQuery日期控件基于jeDate
  18. CocosCreator新手游戏开发指南(真小白)超详细 逐行注释
  19. Springboot毕设项目M11463家居网9m26y(java+VUE+Mybatis+Maven+Mysql)
  20. 王艾辉:下方重点关注3140 上方3190 破位则追

热门文章

  1. java语言不用担心内存吗_不用担心智能手机的电池,只需使用它
  2. 小程序禁用ios 左右滑动_如何在使用应用程序时禁用iOS控制中心
  3. 「读懂源码系列2」我从 lodash 源码中学到的几个知识点
  4. zookeeper学习03 使用场景
  5. 第八课-第二讲 08_02_bash脚本编程之七 case语句及脚本选项进阶
  6. 探索发现:平台云——云的新风向
  7. bzoj3224 Tyvj 1728 普通平衡树题解--Treap
  8. sql练习(针对Mysql)
  9. 部门树形结构,使用Treeview控件显示部门
  10. JavaWeb 项目启动时,后台开启一个线程的方法