C#でWPF学習中「WPFプロジェクトを作成するスクリプト3」

C# コンピュータ
C#

前回にクラスライブラリとコンソールプロジェクトを使えるようにしましたが、今回はシンプルにWPFのアプリケーションを作成するプロジェクトを作成します。

WPFプロジェクトを作成しMicrosoft.Xaml.Behaviors.WpfとReactiveProperty.WPFのパッケージを追加。
そのパッケージが使えるようにソースコードの変更。
ウィンドウが閉じるイベントでデータソース(ViewModel)がDispose()されるようにコードを追加。

ファイル名:Create-WPFProject.ps1

<#
.SYNOPSIS
WPFプロジェクトを作成

.DESCRIPTION
追加パッケージ
Microsoft.Xaml.Behaviors.Wpf
ReactiveProperty.WPF

.EXAMPLE
mkdir プロジェクト名
cd プロジェクト名
Create-WPFProject.ps1

#>

$ErrorActionPreference = "STOP" # エラーが発生した場合スクリプトを停止する。

$ProjectName = Split-Path (Get-Location).Path -Leaf 
$result =Read-Host "Do you want to create a ${ProjectName} Proejct?(Y/N)"
if ($result.ToUpper() -ne "Y") {
    Exit
}

dotnet new wpf # WPFプロジェクトの作成
dotnet add package Microsoft.Xaml.Behaviors.Wpf
dotnet add package ReactiveProperty.WPF

# ViewModel
$MainWindowViewModel = @"
using System.Diagnostics;
using System.ComponentModel;
using System.Reactive.Disposables;

namespace ${ProjectName}
{
    public class MainWindowViewModel : INotifyPropertyChanged, IDisposable
    {
       public event PropertyChangedEventHandler? PropertyChanged;
        protected virtual void OnPropertyChanged(string name)
        {
            if (PropertyChanged is null) return;
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
        private CompositeDisposable Disposable { get; } = new CompositeDisposable();
        public MainWindowViewModel()
        {
            PropertyChanged += (o, e) => {};
        }
        public void Dispose()
        {
            Debug.WriteLine("Dispose()");
            Disposable.Dispose();
        }
    }
}
"@

$outFile = Join-Path (Get-location).Path "MainWindowViewModel.cs"
$writer = New-Object System.IO.StreamWriter($outFile, $false, [System.Text.Encoding]::GetEncoding("utf-8"))
$writer.WriteLine($MainWindowViewModel)
$writer.Close()

# ViewModelCleanupBehavior
$ViewModelCleanupBehavior = @"
using System.Xml;
using System.Xml.Schema;

using Microsoft.Xaml.Behaviors;
using System;
using System.Windows;
using System.ComponentModel;

namespace ${ProjectName}
{
    public class ViewModelCleanupBehavior : Behavior<Window>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.Closed += this.WindowClosed;
        }

        private void WindowClosed(object? sender, EventArgs e)
        {
            (this.AssociatedObject.DataContext as IDisposable)?.Dispose();
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.Closed -= this.WindowClosed;
        }
    }
}
"@
$outFile = Join-Path (Get-location).Path "ViewModelCleanupBehavior.cs"
$writer = New-Object System.IO.StreamWriter($outFile, $false, [System.Text.Encoding]::GetEncoding("utf-8"))
$writer.WriteLine($ViewModelCleanupBehavior)
$writer.Close()

# XAML
$inFile = Join-Path (Get-location).Path "MainWindow.xaml"
$xmlDoc = [System.Xml.XmlDocument](Get-Content -Encoding UTF8 -Raw $inFile)

$ns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
$nslocal = "clr-namespace:${ProjectName}"
$nsi = "clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors"
$nsinteractivity = "clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"

$attri = $xmlDoc.CreateAttribute("xmlns:i")
$attri.Value = $nsi
$xmlDoc.Window.Attributes.Append($attri) | Out-Null

$attri2 = $xmlDoc.CreateAttribute("xmlns:interactivity")
$attri2.Value = $nsinteractivity
$xmlDoc.Window.Attributes.Append($attri) | Out-Null

$xmlDoc.Window.setAttribute("Title", "${ProjectName}")

$child = $xmlDoc.CreateElement("Window.DataContext", $ns)
$child2 = $xmlDoc.CreateElement("local:MainWindowViewModel", $nslocal)

$pos = $xmlDoc.getElementsByTagName("Grid")[0]
$dc = $xmlDoc.Window.insertBefore($child, $pos)
$dc.appendChild($child2) | Out-Null


$child3 = $xmlDoc.CreateElement("i:Interaction.Behaviors", $nsi)
$child4 = $xmlDoc.CreateElement("local:ViewModelCleanupBehavior", $nslocal)

$ib = $xmlDoc.Window.insertBefore($child3, $pos)
$ib.appendChild($child4) | Out-Null

$xmlDoc.Save($inFile) 


cd ..

コメント