使用 DotNet CLI 创建自定义的 WPF 项目模板

640?wx_fmt=jpeg

描述

当我们安装完 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 方式来实现。

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

项目结构如下图所示:

640?wx_fmt=png

其中,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 中,如下图所示:

640?wx_fmt=png

同时,在 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项目模板


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[省选联考 2020 A/B 卷] 信号传递(状压dp + 卡空间)

problem luogu-P6622 一条道路上从左至右排列着 mmm 个信号站&#xff0c;初始时从左至右依次编号为 1,2,…,m1,2,\dots,m1,2,…,m&#xff0c;相邻信号站之间相隔 111 单位长度。 每个信号站只能往它右侧的任意信号站传输信号&#xff08;称为普通传递&#xff09;&#xf…

SP687 REPEATS - Repeats(暂时不会)

SP687 REPEATS - Repeats 题意&#xff1a; 给定字符串&#xff0c;求重复次数最多的连续重复子串 题解&#xff1a; 论文题&#xff0c;暂时不会&#xff0c;搞不清楚原理 代码&#xff1a;

[翻译] ASP.NET Core 利用 Docker、ElasticSearch、Kibana 来记录日志

一步一步指导您使用 ElasticSearch, Kibana, ASP.NET Core 2.1 和 Docker 来记录日志在本教程中&#xff0c;我将向您展示如何启动和运行 ElasticSearch&#xff0c;Kibana 和 ASP.NET Core 2.1在开始之前&#xff0c;让我们来看看 ElasticSearch&#xff0c;Kibana 和 Serilog…

[省选联考 2020 A 卷] 作业题(欧拉反演 + 矩阵树定理 + 高斯消元)

problem luogu-P6624 小 W 刚刚在离散数学课学习了生成树的知识&#xff1a;一个无向图 G(V,E)G(V,E)G(V,E) 的生成树 TTT 为边集 EEE 的一个大小为 ∣V∣−1|V|-1∣V∣−1 的子集&#xff0c;且保证 TTT 的生成子图在 GGG 中连通。 小 W 在做今天的作业时被这样一道题目难住…

P4070 [SDOI2016]生成魔咒

P4070 [SDOI2016]生成魔咒 题意&#xff1a; 有n个字符xi&#xff0c;每次在S的末尾加入一个字符&#xff0c;(一开始S为空)&#xff0c;每次加入xi后的不相同字串有多少个 题解&#xff1a; 做这个题首先要会后缀数组P3809 【模板】后缀排序&#xff0c;还要知道不同的子串…

【学习笔记】WQS二分详解及常见理解误区解释

文章目录应用分析算法分析WQS二分精髓的两点细节&#xff08;博客重点&#xff01;&#xff09;真题分析[国家集训队]Tree Ⅰ忘情星际广播网上很多博客写得模模糊糊的&#xff0c;对我这个新手可是一点都不友好。 昨天一天都在研究这个东西&#xff0c;分享一下自己的拙见。 百…

ASP.NET Core中HTTP管道和中间件的二三事

本文出自《从零开始学ASP.NET CORE MVC》推荐文章&#xff1a;中间件是什么&#xff1f;在.NET Core中的工作原理又是怎样的呢&#xff1f;配置ASP.NET Core请求(Request)处理管道在本视频中&#xff0c;我们将讨论使用中间件组件为asp.net core 应用程序配置请求处理管道。作为…

Codeforces Round #737 (Div. 2)

Codeforces Round #737 (Div. 2) 题号题目知识点AEzzat and Two Subsequences思维&#xff08;略&#xff09;BMoamen and k-subarrays思维(略)CMoamen and XOR二进制DEzzat and Grid线段树思维EAssiut Chess

非平凡回路(bfs)

problem 题目描述 给定一张 nnn 个点的无向图&#xff0c;定义经过一个点 uuu 的非平凡回路为一条从 uuu 出发回到 uuu 的路径&#xff0c;并且至少包含一个简单环。 对于每个点求出经过它的最小非平凡回路长度 lll。 考虑到这个问题很困难&#xff0c;因此你只需要求出 ⌈…

cf1557 C. Moamen and XOR

cf1557 C. Moamen and XOR 题意&#xff1a; 一个n位数&#xff0c;每一位小于2k2^k2k,如果a1&a2&…an>a1⊕a2…⊕an,则获胜 现在给你n和k&#xff0c;问能构造多少个序列是获胜的 题解&#xff1a; 奇偶分类二进制考虑 我们现在认为每个数的第k位都是1 如果n为…

.Net Core Razor 预编译,动态编译,混合编译

预编译预编译是ASP .Net Core的默认方式。在发布时&#xff0c;默认会将系统中的所有Razor视图进行预编译。编译好的视图DLL统一命名为 xxx.PrecompiledViews.dll 或者 xxx.Views.dll动态编译将项目整个配置成动态编译很简单&#xff0c;添加一个配置项目MvcRazorCompileOnPubl…

[CodeForces gym 101630 J] 过路费(最短路)

problem 给定一张图 nnn 个点 mmm 条边&#xff0c;并给定阈值 kkk&#xff0c;以及起终点 s,ts,ts,t。 然后每条边经过都需要支付 www 的花费&#xff0c;形如 (u,v,w)(u,v,w)(u,v,w) 格式给出。 求 s→ts\rightarrow ts→t 的最小花费。 最小花费定义如下&#xff1a; 如…

cf1557D. Ezzat and Grid

cf1557D. Ezzat and Grid 题意&#xff1a; 有n行&#xff0c;每行有10910^9109列&#xff0c;仅仅由0和1构成 现在给你1的存在位置&#xff0c;(i,l,r)表示第i行的第l列到第r列全为1 你可以删除任意一行i&#xff0c;删除后&#xff0c;第i-1行和第i1行为相邻 现在我们要求求…

一张图来看看.NETCore和前后端技术的演进之路

一张图2019年3月10日&#xff0c;在长沙.NET 技术社区组织的技术沙龙《.NET Core和前后端分离那些事儿》上&#xff0c;我们曾经试图通过一系列抽丝剥茧的过程来引导大家在这条基于.NET Core的前后端分离有关的技术路线上持续发散&#xff0c;由于各种原因未能成功&#xff0c;…

【学习笔记】我命由天不由我之随机化庇佑 —— 爬山法 和 模拟退火法

以下均假设最优解是在最低点。 爬山法 爬山算法是一种局部择优的方法&#xff0c;采用启发式方法&#xff0c;是对深度优先搜索的一种改进&#xff0c;它利用反馈信息帮助生成解的决策。 直白地讲&#xff0c;就是当目前无法直接到达最优解&#xff0c;但是可以判断两个解哪…

Strange Memory Gym - 102832F

Strange Memory Gym - 102832F 题意&#xff1a; 有一颗n个节点的树&#xff0c;求下面公式的值&#xff1a; 题解&#xff1a; a ⊕ b c 可以推出a ⊕ c b 那么ai⊕ajalca(i,j)a_{lca(i,j)}alca(i,j)​,可以得到&#xff1a;ai⊕alca(i,j)a_{lca(i,j)}alca(i,j)​aj,ai就…

.net core 使用RSA获取私钥证书并签名

以前我们使用RSA加密主要是使用RSACryptoServiceProvider这个类&#xff0c;在.NET Core中也有这个类&#xff0c;但是这个类并不支持跨平台&#xff0c;所以如果你是用这个类来进行加/解密在windows上运行是完全没有错误的&#xff0c;但是只要你一放到Linux下就会出现异常。查…

2022 联合省选游记 信息奥赛五年退役记

Day0 这可不太美妙&#xff0c;十点就上床睡觉&#xff0c;结果完全睡不着&#xff0c;我妈打呼&#xff0c;加上我当时脑袋也想得多&#xff0c;整个人就挺烦躁的。 翻来覆去可能突然就睡着了&#xff0c;然后醒来虽然没天亮但是我猜至少也有五点多了吧&#xff0c;缓一会看…

CDN流量调度问题(2021CCPC华为云挑战赛)

CDN流量调度问题 题意&#xff1a; 有n个线路&#xff0c;每个线路的任务量为a[i],初始状态下&#xff0c;每个线路起初只有一个节点&#xff0c;每个线路完成任务所需时间为 现在你要给每个线路增加节点&#xff0c;所有增加的节点总数不超过m&#xff0c;第i个线路增加节点…

.NET Core 3.0 Preview 3中关于ASP.NET Core的更新内容

.NET Core 3.0 Preview 3已经推出&#xff0c;它包含了一系列关于ASP.NET Core的新的更新。下面是该预览版的更新列表&#xff1a;Razor组件改进:单项目模板 新的Razer扩展Endpoint路由集成预呈现Razor类库中的Razor组件改进事件处理 Forms & validation运行时编译Worker服…