🐥note.

小鳥とMicrosoft <3 なエンジニアの技術Blog📚

.NET CoreのWPFでWindowを表示するClass Libraryを作成した

実行するとWPFのWindowを表示するClass Libraryを作成しました。

これはClient side Blazorをいい感じにWPFのWebViewで表示できないか試行錯誤してた最中の副産物です。結局ボツ案で使うことは無いとは思いますが、せっかく作ったのでここで供養させてもらいます...
※そもそもアプローチの方向が全然違うでしょうに

プロジェクトの作成

ClassLibraryはWindowLib
呼び出し側はConsoleAppという名前のConsole Applicationを作成します。

ちなみに開発環境は.NET Core 3.1 Preview3です。

mkdir WindowLib\src
cd WindowLib\src
dotnet new sln -n WindowLib
dotnet new console -o ConsoleApp
dotnet new classlib -o WindowLib
dotnet sln add WindowLib.sln ConsoleApp WindowLib
dotnet add .\ConsoleApp\ reference .\WindowLib\

Library側の作成

Library側を作っていきます。

WindowLib.csproj

WPFを扱うのでSDKを変更しUseWPFを指定します。

WPFは.NET Core3.0(netstandard2.1)以上から対応しているので、TargetFrameworkもそこら辺の値に変更します。

ビルド時にMainWindow.xamlをコピーするようContentで指定します。

- <Project Sdk="Microsoft.NET.Sdk">
+ <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

  <PropertyGroup>
-   <TargetFramework>netstandard2.0</TargetFramework>
+  <TargetFramework>netcoreapp3.1</TargetFramework>
+   <UseWPF>true</UseWPF>
  </PropertyGroup>

+ <ItemGroup>
+   <Content Include="MainWindow.xaml">
+     <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+   </Content>
+ </ItemGroup>
</Project>

MainWindow.xaml

とりあえずのWindowを作成します。

<Window
       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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       xmlns:local="clr-namespace:WindowLib"
       mc:Ignorable="d"
       Title="MainWindow" Height="450" Width="800">
    <TextBlock Text="Hello WPF World."></TextBlock>
</Window>

Class1.cs

STAThreadで動作させます。
MainWindow.xamlを読み込んでWindowクラスにキャストして起動するだけです。 ※ファイル名・クラス名は適宜変えてください...

using System;
using System.IO;
using System.Threading;
using System.Windows;
using System.Xml;
using System.Windows.Markup;
using System.Reflection;

namespace WindowLib
{
    public class Class1
    {
        [STAThread]
        public static void Run()
        {
            var th = new Thread(new ThreadStart(runApp));
            th.SetApartmentState(ApartmentState.STA);
            th.Start();
        }

        private static void runApp()
        {
            Application app = new Application();
            Window window = new Window();

            var filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "MainWindow.xaml");
            using (FileStream infs = new FileStream(filePath, FileMode.Open))
            {
                XmlReader xmlReader = XmlReader.Create(infs);
                window = (Window)XamlReader.Load(xmlReader);
            }

            app.Run(window);
        }
    }
}

呼び出し側の作成

WindowLibを使う側のアプリであるConsoleAppのコードです。

Program.cs

呼び出すだけです

using System;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
-           Console.WriteLine("Hello World!");
+           WindowLib.Class1.Run();
        }
    }
}

以上で完成です。

実行

ファイル構成はこんな感じです。

f:id:piyo_esq:20191121211253p:plain
ファイル構成

ConsoleAppディレクトリに移動してdotnet runで実行します。

f:id:piyo_esq:20191121211311p:plain
実行結果

;csprojにContentを記載したおかげでdotnet publish -c Releaseで発行すると bin\Release\netcoreapp3.1\publishMainWindow.xamlがしっかり出力されていますね。

f:id:piyo_esq:20191121211327p:plain
publishフォルダ

おわり

供養完了(なむなむ