使用 DotNet CLI 創建自定義的 WPF 項目模板

来源:https://www.cnblogs.com/hippieZhou/archive/2019/04/15/10691339.html
-Advertisement-
Play Games

描述 當我們安裝完 DotNetCore 3.0 版本的 SDK 後,我們就可以創建基於 DotNetCore 的 WPF 項目模板,通過如下 CLI 可以方便快捷的創建並運行我們的項目: 做過 WPF 開發的朋友都知道,這個項目模板肯定不符合我們的預期,我們希望我們的項目模板能夠加入 MVVM 的 ...


描述

當我們安裝完 DotNetCore 3.0 版本的 SDK 後,我們就可以創建基於 DotNetCore 的 WPF 項目模板,通過如下 CLI 可以方便快捷的創建並運行我們的項目:

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 命令進行安裝

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

註:因為我們使用了 DotNetCore,所以我們儘量讓我們安裝的第三方包是基於 .NET Standard 方式來實現。

然後,嘗試修改我們的這個項目,把它改成我們以後期望創建的項目模板的樣子。可以參考我的如下修改:

項目結構如下圖所示:

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

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 的示例代碼如下所示:

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 的示例代碼如下所示:

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 的示例代碼如下所示:

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 的示例代碼如下所示:

<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 的示例代碼如下所示:

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 的示例代碼如下所示:

<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 的示例代碼如下所示:

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 文件,進行如下示例配置:

{
    "$schema": "http://json.schemastore.org/template",
    "author": "hippiezhou <[email protected]>",
    "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 所在的目錄),然後執行下述安裝操作

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 結點下新增一個如下的節點內容:

 {
      "ConfigMountPointId": "f3861181-7a43-4fc5-ab1c-12d95e734c0a",
      "Author": "hippiezhou <[email protected]>",
      "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 中取消應用了。

我們可以使用下述操作進行測試一下:

# 使用我們自定義的項目模板,創建 wpf 項目
dotnet new wpf-mvvmlight -n test

cd test

dotnet restore

dotnet run

如果不出意外的話,我們就可以看到這個項目的代碼段和我們自定義的模板代碼段是一樣的。

如果卸載我們的項目模板可以使用如下命令:

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

註:我們需要確保我們的自定義模板不能丟失,要不然到時候就卸載就麻煩了(至少目前看來是這樣的)。

關於如何將我們的自定義模板可以上傳到 NuGet 供別人下載使用,這裡就不做介紹了,具體操作可參考園裡介紹如何在 DotNetCore MVC 中打造自己的項目模板方法是一樣的。我在本文中的創建的代碼模板也不會提交上去,還是等著 MVVMLight 的原作者 Laurent Bugnion 來操刀會好一些。

總結

本文介紹瞭如何通過 DotNet CLI 來創建自定義的 WPF 項目模板。在實際的使用過程中,CLI 的功能和支持的參數會更多,所以感興趣的朋友可以自行研究。

相關參考


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 軟工作業2 ——實現一個能夠對文本文件中的單詞的詞頻進行統計的控制台程式 1.Github地址: https://github.com/wangshiyaoyao/WordCont 2.PSP表格 PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際 ...
  • 異常 異常指的是程式中的不正常現象,一般異常都是由第三方數據的使用造成的。java中每種異常現象都會有一個對應的異常類。java對異常的處理方式就是終止程式。異常機制其實是為了幫助我們找到程式中的問題。異常指的並不是語法錯誤,語法錯了,編譯不通過,不會產生位元組碼文件,根本不能運行。 異常體系 jav ...
  • 今天我們繼續學習一下Numpy庫的學習 廢話不多說 ,開始講 比如我們現在想創建一個0-14這樣一個15位的數組 可以直接寫,但是很麻煩,Numpy中就給我們了一個方便創建的方法 numpy中有一個arange函數 運行這段代碼以後,可以得到如下結果 這裡我們可以看到,我先列印了一下,np.aran ...
  • 如果系統採用前後端分離的話,項目中就需要用到網關了,為了保證系統的安全性。 前後端項目簡單架構圖: 1. 基於網關實現白名單和黑名單攔截(防止惡意請求)、ip限流。 2. API介面實現Token授權驗證。 3. 使用MD5實現API介面驗證簽名,防止抓包篡改數據。 4. 實現API介面安全加密傳輸 ...
  • HashSet怎麼保證添加元素不重覆? HashSet是否允許null元素? HashSet是有序的嗎? HashSet是同步的嗎? 什麼是fail-fast? ...
  • 7、Multi Get API(Multi Get API) multi GET API 允許你一次性獲取多個文檔,你需要指定 數組,其中包含了所有你需要查詢的文檔,每個查詢結構至少包含索引,類型和文檔id。如果操作過程中遇到錯誤將會返回錯誤信息。返回的結果與 GET API 的結果結構類似。 如下 ...
  • Map集合 在Map集合中保存的數據為一組數據,其中:一個數據為key,另外一個數據為value。而key和value具備對應的關係,在集合中它們屬於一組(一對)數據。而每個key只能對應唯一的一個value值並且所有的key不能重覆。 但是其中的value值是可以重覆的。 Collection中的 ...
  • 6、Update By Query API 介面可以在不改變 source 的情況下對 index 中的每個文檔進行更新。這對於獲取新屬性或其他聯機映射更改很有用。以下是 API: 這將返回如下內容: _update_by_query 在開始執行的時候獲得一個快照,並使用內部版本控制對找到的內容進行 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...