https://github.com/Exathi/Powershell-WPF
簡単なハンズオンで学ぶWPFのデータバインディングからのMVVM
/
├── CreateClassInstanceHelper.psm1 # PowerShellクラスのインスタンス生成を支援するモジュール
│ ├── $Script:powershell # PowerShellインスタンスを保持するグローバル変数
│ ├── $Script:body # クラスインスタンス生成用の関数定義を含む文字列
│ ├── function Initialize() # PowerShellインスタンスの初期化とスクリプト実行関数
│ └── function New-UnboundClassInstance( # ランスペースに束縛されていないクラスインスタンスを生成
│ [Type] $type, # 生成するクラスの型
│ [object[]] $arguments # コンストラクタの引数配列
│ )
│
├── WPFClassHelpers.psm1 # WPFアプリケーション構築支援モジュール
│ ├── function New-WPFObject( # XAMLからWPFオブジェクトを生成する関数
│ │ [string] $Path, # XAMLファイルのパス
│ │ [string] $Xaml, # XAML文字列
│ │ [string] $BaseUri # リソース参照の基準URI
│ │ )
│ └── class ThreadManager # 非同期処理を管理するクラス
│ ├── $RunspacePool # PowerShellコマンドを実行するためのプール
│ ├── $DisposeTaskDelegate # リソース解放用デリゲート
│ ├── constructor( # 初期化処理
│ │ [string]$FunctionName
│ │ )
│ ├── Dispose() # リソースの解放
│ ├── [object]Async( # 非同期実行メソッド(オーバーロード3種)
│ │ [scriptblock]$scriptblock, # 実行するスクリプトブロック
│ │ [Delegate]$MethodToRunAsync, # 実行するメソッド
│ │ [Delegate]$Callback # 完了時のコールバック
│ │ )
│ └── [Delegate]CreateDelegate( # デリゲート生成メソッド
│ [PSMethod]$Method, # 対象メソッド
│ $Target # ターゲットオブジェクト
│ )
│
├── ViewModel.ps1 # MVVMパターンのViewModelクラス定義
│ └── class MyViewModel : ViewModelBase # UIとデータを仲介するクラス
│ ├── $SharedResource # 共有リソース値
│ ├── $SharedResourceLock # 共有リソースのロックオブジェクト
│ ├── $Jobs # 実行中ジョブのコレクション
│ ├── $JobsLock # ジョブコレクションのロックオブジェクト
│ ├── $AddTenSlowlyCommand # 数値を10増やすコマンド
│ ├── $ExternalMethodCommand # 外部メソッド実行コマンド
│ ├── $CmdletInMethodCommand # Cmdlet実行コマンド
│ └── constructor() # 初期化処理
│
├── Views/ # UI定義ファイル群
│ ├── Common.xaml # 共通リソース定義
│ │ ├── ResourceDictionary # リソース辞書
│ │ ├── RightMarginConverter # マージン計算用コンバーター
│ │ ├── Colors # 色定義
│ │ ├── Styles # スタイル定義
│ │ │ ├── TextBlockShowCase # 表示用テキストブロック
│ │ │ ├── TextBlockLabel # ラベル用テキストブロック
│ │ │ ├── TextBlockData # データ表示用テキストブロック
│ │ │ ├── TitleBarButton # タイトルバーボタン
│ │ │ └── TitleBarButtonRestore # 復元ボタン
│ │ ├── ControlTemplates # コントロールテンプレート
│ │ └── StreamGeometry # 図形定義
│ │
│ ├── MainWindow.xaml # メインウィンドウ定義
│ │ └── Window # ウィンドウ要素
│ │ ├── Resources # ウィンドウリソース
│ │ └── Grid # メインレイアウトグリッド
│ │
│ └── PartialWindow.xaml # カスタムウィンドウ定義
│ └── local:PartialWindow # カスタムウィンドウ要素
│ ├── Resources # ウィンドウリソース
│ └── WindowChrome # ウィンドウ装飾定義
│
└── SampleGUI.ps1 # アプリケーションのエントリーポイント
├── モジュールのインポート # 必要なモジュールの読み込み
├── $ThreadManager # スレッド管理インスタンス
├── $MyViewModel # ViewModelインスタンス
└── WPFウィンドウの初期化と表示 # UIの構築と表示
classDiagram
%% ViewModels フォルダ
namespace ViewModelsフォルダ {
class ViewModelBase {
+PropertyChanged : Event
+add_PropertyChanged(handler) : void
+remove_PropertyChanged(handler) : void
+RaisePropertyChanged(propertyName) : void
note "UIの更新通知の基盤となるクラス
- プロパティの変更を検知してUIに通知
- データバインディングの基本機能を提供
- すべてのViewModelの親クラス"
}
class ActionCommand {
+CanExecute(parameter) : bool
+Execute(parameter) : void
+RaiseCanExecuteChanged() : void
-$Action : Action
-$ActionObject : object
-$CanExecuteAction : Func
-$ThreadManager : ThreadManager
-$Workers : int
-$Throttle : int
note "UIのアクション(ボタンクリックなど)を処理
- 非同期処理のサポート
- スロットリング制御
- 実行可否の動的制御
- マルチスレッド対応"
}
}
%% Helpers フォルダ
namespace Helpers {
class ThreadManager {
+Dispose() : void
+Async(methodToRunAsync, callback) : Task
+CreateDelegate(method, target) : Delegate
-$SharedPoolVars : object
-$RunspacePool : RunspacePool
note "非同期処理の管理クラス
- PowerShellランスペースの管理
- スレッドプールの制御
- 非同期タスクの実行と監視
- リソースの適切な解放"
}
}
%% 継承関係
ActionCommand --|> ViewModelBase : 継承
ActionCommand --|> System.Windows.Input.ICommand : 実装
ThreadManager --|> System.IDisposable : 実装
%% 依存関係
ActionCommand ..> ThreadManager : 使用
classDiagram
class ViewModelBase {
+PropertyChanged : Event
+add_PropertyChanged(handler) : void
+remove_PropertyChanged(handler) : void
+RaisePropertyChanged(propertyName) : void
%% ViewModelBase (ビュー・モデル・ベース):
%% プロパティの変更を通知するための基礎クラスです。
%% INotifyPropertyChangedインターフェースを実装しており、
%% UIにプロパティの変更を通知します。
}
class ActionCommand {
+CanExecute(parameter) : bool
+Execute(parameter) : void
+RaiseCanExecuteChanged() : void
-$Action : Action
-$ActionObject : object
-$CanExecuteAction : Func
-$ThreadManager : ThreadManager
-$Workers : int
-$Throttle : int
-$InvokeCanExecuteChangedDelegate : Delegate
-$Dispatcher : Dispatcher
%% ActionCommand (アクション・コマンド):
%% WPFのコマンドパターンを実装し、UIアクションを処理するクラスです。
%% ViewModelBaseを継承し、ICommandインターフェースを実装しています。
}
class ThreadManager {
+Dispose() : void
+Async(methodToRunAsync, callback) : Task
+CreateDelegate(method, target) : Delegate
-$SharedPoolVars : object
-$DisposeTaskDelegate : Delegate
-$RunspacePool : RunspacePool
%% ThreadManager (スレッド・マネージャー):
%% 非同期処理や並列処理を管理するクラスです。
%% IDisposableインターフェースを実装しており、リソースの解放を行います。
}
ActionCommand --|> ViewModelBase : 継承
ActionCommand --|> System.Windows.Input.ICommand
ThreadManager --|> System.IDisposable
classDiagram
class New-UnboundClassInstance {
+Initialize() : void
+New-UnboundClassInstance(type, arguments) : object
%% New-UnboundClassInstance (ニュー・アンバウンド・クラス・インスタンス):
%% PowerShellクラスのインスタンスを作成するためのヘルパークラスです。
%% ランスペースに束縛されないインスタンスを作成します。
}
class SampleGUI {
+MainWindow : Window
+PartialWindow : Window
%% SampleGUI (サンプルGUI):
%% GUIアプリケーションのエントリーポイントとなるクラスです。
%% MainWindowやPartialWindowを表示します。
}
classDiagram
class MainWindow {
+MainGrid : Grid
+TitleBar : UIElement
+JobGrid : DataGrid
%% MainWindow (メイン・ウィンドウ):
%% アプリケーションのメインウィンドウを定義するクラスです。
%% UI要素やレイアウトを含みます。
}
class PartialWindow {
+MainGrid : Grid
+TitleBar : UIElement
+JobGrid : DataGrid
%% PartialWindow (パーシャル・ウィンドウ):
%% 特定のUIレイアウトを持つウィンドウを定義するクラスです。
}
class Common {
+Styles : ResourceDictionary
+Resources : ResourceDictionary
%% Common (コモン):
%% アプリケーション全体で使用されるスタイルやリソースを定義するクラスです。
}
flowchart TD
A[アプリケーション開始] --> B[New-UnboundClassInstanceで<br>クラスインスタンス作成<br>CreateClassInstanceHelper.psm1]
%% 各ステップの説明
B -->|PowerShellクラスの<br>インスタンスを作成| C[ViewModelBaseの<br>プロパティ変更通知設定<br>ViewModel.ps1]
C -->|プロパティ変更をUIに通知| D[ActionCommandの<br>コマンド設定]
D -->|UIアクションを処理| E[ThreadManagerで<br>非同期処理設定]
E -->|非同期処理を管理| F[SampleGUIでGUI表示]
F -->|GUIアプリケーションの<br>エントリーポイント| G[MainWindowの<br>UI要素設定]
G -->|メインウィンドウの設定| H[PartialWindowの<br>UI要素設定]
H -->|特定のUIレイアウトの設定| I[アプリケーション終了]
flowchart TD
A[アプリケーション開始] --> B
subgraph SampleGUI.ps1
B[SampleGUI.ps1 メイン処理]
B --> C[モジュールとアセンブリの読み込み]
C --> D[New-WPFObject]
D --> E[ウィンドウの表示]
end
subgraph CreateClassInstanceHelper.psm1
F[New-UnboundClassInstance]
end
subgraph ViewModel.ps1
G[ViewModelBase クラス]
H[ActionCommand クラス]
I[ThreadManager クラス]
J[RightMarginConverter クラス]
end
subgraph WPFClassHelpers.psm1
K[New-WPFObject]
end
subgraph XAML ファイル
subgraph MainWindow.xaml
L[MainWindow]
end
subgraph PartialWindow.xaml
M[PartialWindow]
end
subgraph Common.xaml
N[共通リソース]
end
end
B --> F
B --> G
B --> H
B --> I
B --> J
D --> K
E --> L
E --> M
L --> N
M --> N
subgraph UI コンポーネント
O[メニュー]
P[グループボックス]
Q[DataGrid]
end
M --> O
M --> P
M --> Q
R[アプリケーション終了]
E --> R
flowchart TB
Start([開始]) --> ModuleImport[モジュールのインポート<br>using module/namespace]
subgraph Init[初期化処理]
ModuleImport --> AssemblyLoad[アセンブリの動的読み込み<br>Add-Type]
AssemblyLoad --> ModuleLoad[モジュールの読み込み<br>Import-Module/ドット演算子]
ModuleLoad --> ThreadMgr[ThreadManager<br>インスタンス作成]
ThreadMgr --> ViewModel[ViewModel<br>インスタンス作成]
ViewModel --> CreateBtn[ボタンの作成]
end
Init --> EnableSync[Jobsコレクションの<br>同期有効化]
subgraph WindowSetup[ウィンドウ設定]
EnableSync --> CreateWPF[WPFオブジェクト作成<br>New-WPFObject]
CreateWPF --> SetContext[DataContext設定]
end
WindowSetup --> ShowDialog[ダイアログ表示]
ShowDialog --> WaitClose{ウィンドウが<br>閉じられる?}
WaitClose -->|No| ShowDialog
WaitClose -->|Yes| ShowResult[ジョブ結果の表示<br>Format-Table]
ShowResult --> End([終了])
%% コメントアウトされている処理を点線で表示
style EventHandler stroke-dasharray: 5 5
WaitClose -.-> EventHandler[/Closingイベントハンドラ/]
EventHandler -.-> Dispose[ThreadManagerの<br>Dispose]
flowchart TB
subgraph MyViewModel[MyViewModelクラス]
direction TB
Init[初期化処理] --> Props[プロパティ定義]
Props --> |初期化| SharedRes[共有リソース管理]
Props --> |初期化| Jobs[ジョブ管理]
Props --> |初期化| Calc[計算サービス]
subgraph Commands[コマンド管理]
Delegates[デリゲート定義] --> CmdBinding[コマンドバインディング]
CmdBinding --> AddTen[AddTenSlowlyCommand]
CmdBinding --> External[ExternalMethodCommand]
CmdBinding --> Cmdlet[CmdletInMethodCommand]
end
end
subgraph PartialWindow[PartialWindowクラス]
direction TB
Constructor[コンストラクタ] --> SystemCmd[システムコマンド<br>バインディング]
SystemCmd --> ShowMenu[ShowSystemMenu]
SystemCmd --> Minimize[MinimizeWindow]
SystemCmd --> Maximize[MaximizeWindow]
SystemCmd --> Restore[RestoreWindow]
SystemCmd --> Close[CloseWindow]
subgraph WindowOps[ウィンドウ操作]
ShowMenu --> MenuPopup{システムメニュー<br>表示}
Minimize --> MinState{最小化}
Maximize --> MaxState{最大化}
Restore --> NormalState{通常サイズ}
Close --> CloseWin{ウィンドウを<br>閉じる}
end
end
style MyViewModel fill:#f9f,stroke:#333,stroke-width:2px
style PartialWindow fill:#bbf,stroke:#333,stroke-width:2px
style Commands fill:#ffe,stroke:#333,stroke-width:1px
style WindowOps fill:#efe,stroke:#333,stroke-width:1px
flowchart TB
subgraph New-WPFObject[New-WPFObject関数]
direction TB
Start([開始]) --> CheckParams{パラメータ<br>チェック}
CheckParams -->|Path指定| ReadFile[ファイルから<br>XAMLを読み込み]
CheckParams -->|Xaml指定| UseXaml[XAMLを<br>直接使用]
subgraph ParseProcess[XAMLパース処理]
ReadFile --> CheckDynamic{Dynamic<br>モード?}
UseXaml --> CheckDynamic
CheckDynamic -->|Yes| SetupContext[ParserContextの<br>設定]
SetupContext --> ParseWithContext[XAMLReaderで<br>パース]
CheckDynamic -->|No| ParseDirect[直接パース]
end
ParseWithContext --> ReturnObj[WPFオブジェクト<br>を返す]
ParseDirect --> ReturnObj
ReturnObj --> End([終了])
end
subgraph ThreadManager[ThreadManagerクラス]
direction TB
InitTM[初期化] --> CreatePool[RunspacePool作成]
CreatePool --> SetupAsync[非同期処理設定]
subgraph AsyncOps[非同期操作]
SetupAsync --> ExecAsync[Async実行]
ExecAsync --> CreateTask[タスク作成]
CreateTask --> SetCallback[コールバック設定]
end
SetCallback --> Cleanup[クリーンアップ]
end
style New-WPFObject fill:#f9f,stroke:#333,stroke-width:2px
style ThreadManager fill:#bbf,stroke:#333,stroke-width:2px
style ParseProcess fill:#efe,stroke:#333,stroke-width:1px
style AsyncOps fill:#ffe,stroke:#333,stroke-width:1px