WPFにおけるPrism集中講座(6) EventAggregatorとregionを使う

14-UsingEventAggregator Description には Using the IEventAggregator とあります。 まんま過すぎですね。 動かしてみると、TextBox に入力した内容を「Send Message」で送ると、 ListBox に追加されるというサンプルのようです。 UsingEventAggregator 内の App.xaml.cs using System.Windows; using UsingEventAggregator.Views; namespace UsingEventAggregator { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : PrismApplication { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { } protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { moduleCatalog.AddModule<ModuleA.ModuleAModule>(); moduleCatalog.AddModule<ModuleB.ModuleBModule>(); } } } UsingEventAggregator 内の Views\MainWindow.xaml <Window x:Class="UsingEventAggregator.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="525" Height="350" prism:ViewModelLocator.AutoWireViewModel="True"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <ContentControl prism:RegionManager.RegionName="LeftRegion" /> <ContentControl Grid.Column="1" prism:RegionManagerRegionName="RightRegion" /> </Grid> </Window> UsingEventAggregator 内の ViewsModels\MainWindowViewModel.cs namespace UsingEventAggregator.ViewModels { public class MainWindowViewModel : BindableBase { private string _title = "Prism Unity Application"; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } public MainWindowViewModel() { } } } ModuleA プロジェクトと ModuleB プロジェクトを ContentControl で読み込んでいるようです。 ...

2025年01月19日 · 11 分 · ☨もりゃき.xyz☨

WPFにおけるPrism集中講座番外編:Prismの複雑怪奇なCommand周りをCommunityToolkit.Mvvmで実装する

まずはプロジェクトの作成と整備ね さあ、CommunityToolkit.Mvvm 大好きな、もりゃきお姉ちゃんがやってきましたよ! ますは、サクサクプロジェクトを作りましょう。 Visual Studioで「WPFアプリケーション」を選んで、ソリューション名は「TabCommandSample」、フレームワークは「.NET 9」選択でいいでしょう! 次に、NuGet経由で「CommunityToolkit.Mvvm」と「Microsoft.Extensions.DependencyInjection」をいつもの通りにインストールしましょうね! あ、CommunityToolkit.Mvvm V8 を使うから、エラーが出たらとりあえずリビルドしてね、お姉さんとの約束よ! 次は DI の設定よ!こんなの App.xaml.cs に書くだけなんだから、たくさんアプリケーション作る人はコピペできるようにしとくのが賢い子☆ public partial class App : Application { /// <summary> /// サービスの登録をします /// </summary> public App() { Services = ConfigureServices(); Ioc.Default.ConfigureServices(Services); } /// <summary> /// 現在の App インスタンスを取得します /// </summary> public new static App Current => (App)Application.Current; /// <summary> /// サービスプロバイダです /// </summary> public IServiceProvider Services { get; } /// <summary> /// サービスを登録します /// </summary> /// <returns></returns> private static ServiceProvider ConfigureServices() { var services = new ServiceCollection(); services.AddSingleton<IMessenger, WeakReferenceMessenger>(); services.AddSingleton<IMainWindowViewModel, MainWindowViewModel>(); return services.BuildServiceProvider(); } } 次はエラーが出た MainWindowViewModel の設定だけど、まとめてやっちゃうわよ! プロジェクトにとりあえず Views と ViewModels フォルダを作って MainWindow.xaml を Views に移動、名前空間も手動作業含めて調整。 ...

2025年01月18日 · 4 分 · ☨もりゃき.xyz☨

WPFにおけるPrism集中講座(5) ViewModelとCommandを使う

08-ViewModelLocator Descriptionには using the ViewModelLocator と書かれています。 このサンプルでは、アプリケーションのタイトルが変更されます。 Views\MainWindow.xaml <Window x:Class="ViewModelLocator.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="525" Height="350" prism:ViewModelLocator.AutoWireViewModel="True"> <Grid> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </Grid> </Window> ViewModels\MainWindowViewModel.cs namespace ViewModelLocator.ViewModels { public class MainWindowViewModel : BindableBase { private string _title = "Prism Unity Application"; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } public MainWindowViewModel() { } } } まあ、これ CommunityToolkit.Mvvm の覚え書き をきちんと読んでくれた人なら「ほとんど同じ」となりますよね? CommunityToolkit.Mvvm では ObservableObject だったところが BindingBase になっているだけです。 違いは、View…ここでは MainWindow.xaml.cs に当たりますが、 ここで DataContext に設定しなくても動くことでしょうか? ...

2025年01月17日 · 7 分 · ☨もりゃき.xyz☨

WPFにおけるPrism集中講座(4) ソリューション内のプロジェクトを利用する

07-Modules-AppConfig Description には Load modules using an App.config file と書かれています。 さて、これは何でしょうね?実行したら「View A」と表示されます。 ソリューションを見てみると、プロジェクト「Modules」と「ModuleA」があります。 おそらく「Modules」から「ModuleA」のView を使っているのでしょう。 App.config <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf" /> </configSections> <startup> </startup> <modules> <module assemblyFile="ModuleA.dll" moduleType="ModuleA.ModuleAModule, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ModuleAModule" startupLoaded="True" /> </modules> </configuration> 更新されたファイル単体では分かりにくいので、06-ViewActivationDeactivation の App.config を引用してみます。 <?xml version="1.0" encoding="utf-8"?> <configuration> <startup> </startup> </configuration> はい、見事に空っぽですね。 実際 ModuleA フォルダを bin を基準に掘っていくと ModuleA.dll があります。 では ModuleA にある肝心の変更部分を見てみましょう。 ModuleA\ModuleAModule.cs using ModuleA.Views; namespace ModuleA { public class ModuleAModule : IModule { public void OnInitialized(IContainerProvider containerProvider) { var regionManager = containerProvider.Resolve<IRegionManager>(); regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA)); } public void RegisterTypes(IContainerRegistry containerRegistry) { } } } 他の変更は些細なものなので省略します。 ...

2025年01月16日 · 3 分 · ☨もりゃき.xyz☨

WPFにおけるPrism集中講座(3) 試しにViewのサンプルを書いてみる

プロジェクトの下準備 まず、MainWindow からメニューで「設定」を開いて、設定画面から「設定終了」ボタンで MainWindow に戻るサンプルです。 新規ソリューションを「WPFアプリケーション」で作成します。.NET 9 を利用すれば良いでしょう。 ここでは SimplePrismViewSample という名前にしています。 そして、NuGet から Prism.Unity をインストールします。自分は Visual Studio の NuGet 管理から入れていますが、dotnet 等を扱える人に、改めての説明は不要でしょう。 App.xaml 周辺の設定 Views の設定 ソリューションエクスプローラで Views フォルダを作り、MainWindow.xaml を Views フォルダに移動します。 デフォルトのソリューション直下に MainWindow.xaml を置いていたら、以下の書き換えでエラーを吐きます。 …一体どこに Views が含まれてるんですかね?ブラックボックス臭い… MainWindow.xaml の修正 <Window x:Class="SimplePrismViewSample.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="SimplePrismViewSample" Width="525" Height="350"> <Grid> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </Grid> </Window> MainWindow.xaml の位置を移動したので、x:Class="SimplePrismViewSample.MainWindow" を x:Class="SimplePrismViewSample.Views.MainWindow" に書き換える必要があります。 App.xaml の記述 App.xaml を以下のように書き換えます。 <prism:PrismApplication x:Class="SimplePrismViewSample.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SimplePrismViewSample" xmlns:prism="http://prismlibrary.com/"> <Application.Resources /> </prism:PrismApplication> App.xaml.cs の記述 App.xaml.cs を以下のように書き換えます。 ...

2025年01月15日 · 2 分 · ☨もりゃき.xyz☨

WPFにおけるPrism集中講座(2) region の謎

04-ViewDiscovery Descriptionには Automatically inject views with View Discovery とあります。 やっと動きがありました。とはいえ、アプリケーションを動かしても「View A」と表示されるだけですけどね… App.xaml <prism:PrismApplication x:Class="ViewDiscovery.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ViewDiscovery" xmlns:prism="http://prismlibrary.com/"> <Application.Resources /> </prism:PrismApplication> App.xaml.cs using System.Windows; using ViewDiscovery.Views; namespace ViewDiscovery { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : PrismApplication { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { } } } MainWindow.xaml <Window x:Class="ViewDiscovery.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="Shell" Width="525" Height="350"> <Grid> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </Grid> </Window> MainWindow.xaml.cs using System.Windows; namespace ViewDiscovery.Views { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow(IRegionManager regionManager) { InitializeComponent(); //view discovery regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA)); } } } ここで、ContentRegion にリージョン ViewA を割りあてているのでしょう。 ...

2025年01月14日 · 3 分 · ☨もりゃき.xyz☨

WPFにおけるPrism集中講座(1) 序盤のサンプルについて

Prismについて 正直、この記事を読んでいる方には、今さら説明は不要でしょう。 特にこの記事はWPFを中心に書いているため、WPFとPrismといえばMVVMのためのライブラリ。そのPrismについて徹底解説をしていこうと思います。 PrismLibrary/Prism-Samples-Wpf 01-BootstrapperShell 正直、このサンプルに戸惑った人は多いのではないでしょうか? Descriptionoには Create a basic bootstrapper and shell と書かれています。 初期プロジェクトから書き換え、追記されているのは以下の通りです。 App.xaml <Application x:Class="BootstrapperShell.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:BootstrapperShell"> <Application.Resources /> </Application> App.xaml.cs using System.Windows; namespace BootstrapperShell { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var bootstrapper = new Bootstrapper(); bootstrapper.Run(); } } } MainWindow.xaml <Window x:Class="BootstrapperShell.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Shell" Width="525" Height="350"> <Grid> <ContentControl Content="Hello from Prism" /> </Grid> </Window> Bootstrapper.cs using System.Windows; using BootstrapperShell.Views; namespace BootstrapperShell { class Bootstrapper : PrismBootstrapper { protected override DependencyObject CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { } } } ざっくり言うと App.xaml.cs から Bootstrapper インスタンスを生成して、それを走らせ Run するわけですね。 で Bootstrapper.cs では PrismBootstrapper という、よく分からないブートストラッパが継承されています。 ...

2025年01月13日 · 2 分 · ☨もりゃき.xyz☨

カップ麺シリーズ:CommunityToolkit.Mvvm V8の覚え書き

前提条件 まずは以下の記事内容を踏まえてください。 カップ麺シリーズ:一から学べるWPF における CommunityToolkit.Mvvm(MVVM ToolKit) 覚え書き(1) 簡単な依存性注入とデータバインディング カップ麺シリーズ:一から学べる、WPF における CommunityToolkit.Mvvm(MVVM ToolKit) 覚え書き(2) 依存性注入を利用した簡単なサンプル カップ麺シリーズ:一から学べるWPF における CommunityToolkit.Mvvm(MVVM ToolKit) 覚え書き(3) メッセージングの簡単なサンプル CommunityToolkit.Mvvm V8について 今回、プロジェクト作成は行いません。覚え書き(1)に沿って、最低限コンパイルできる所まで進めてください。 CommunityToolkit.Mvvm V8 は、ざっくり言うと、繰り返しとなる記述を省略できる仕組みが取り入れられています。 [ObservableProperty] 例えば以下のコード private string _username = string.Empty; public string Username { get => _username; set => SetProperty(ref _username, value); } であれば [ObservableProperty] private string _username = string.Empty; で済みます。 実際はこの時クラスが partial になり、裏側で同等のコードが生成あされています。コンパイルエラーが出ることもあるので、partial クラスになることは最低限覚えておきましょう。 そして、このようなコード private string _username = string.Empty; public string Username { get => _username; set { SetProperty(ref _username, value); NameCommand.NotifyCanExecuteChanged(); } } では、結局従来型の利用方法になるじゃないかと思ったでしょうが、ご安心を。このようにします。 ...

2025年01月12日 · (2025年09月11日 更新) · 3 分 · ☨もりゃき.xyz☨

カップ麺シリーズ:WPFを中心としたMVVM論

はじめに この記事は、そこそこ攻撃的な内容になります。不快に思ったなら、その時点でブラウザバックをしてください。 MVVM とは? MVVMは言うまでもなく Model - View - ViewModel を利用した設計手法で、WPFのみならず .NET MAUI などでも利用されます。 そこで、MVVMを活用するにはどうすればいいのか、という点を中心に語りたいと思います。 まず、論外なのは ViewModel と Model を相互参照するパターンです。 View は ViewModel を知っているが、ViewModel は View を知らない。ViewModel は Model を知っているが、Model は ViewModel を知らない。これが大原則です。 何故かというと、Model とはそれ単体でアプリケーションロジックを全て網羅してるからです。特定の ViewModel に依存してはいけません。 例えば、WPF でアプリケーションを作っている時に、Model は「Modelさえ流用すればコンソールアプリだって作れる」そういう状況が理想です。 …いや、理想っていうか、MVVMってそういうモノなんですけどね? 故に、Model が ViewModel を参照しているサイト…正直私も参照したことがありますが、あの人はおそらく MVVM の根本を分かっていないでしょう。 Model から ViewModel に何かを伝えるためには? Model は ViewModel を知らないのが大原則、ではどうすればいいのか?一応の答えは「イベント通知」になります。 ただし、ある程度の規模になると面倒で複雑で、正直やっていられません。私もサンプルコードを提示できません。 ただし、PrismのEvent AggregatorやCommunityToolkit.MVVMのMessengerといったメッセージングを使えるなら、話はグッと楽になります。 Model から ViewModel にメッセージを飛ばせば良いのです。 メッセージングを利用することで疎結合が守られ、ユニットテストも容易になり、さらにViewModelに依存しない構成を作れます。 さて、ここで読者の皆さんは何か気づきませんか?思い当たる節がなければそれに超したことはありませんが… Model で ObservableCollection を使うのは基本的に誤りです!ObservableCollection は ViewModel から View に更新通知するコレクションですから。 ...

2024年11月23日 · 1 分 · ☨もりゃき.xyz☨

カップ麺シリーズ:一から学べる、WPFでの多言語対応方法

多言語対応をしよう 今やグローバル時代!世界を相手にしなければ勝てない! そう、東京弁だけでなく大阪弁、名古屋弁、博多弁など…ごめんなさい調子に乗りました、単純に「日本語」「英語」「ロシア語」対応について語ります。 真面目な話、ソフトウェアで最低限英語対応すると、ターゲットが英語圏の人にまで届く可能性が高まります。 もちろん、ドキュメントも英語化が必要ですけど、今ならDeepLとか使えば便利にそれっぽく翻訳してくれますからね。 さらにChatGPTで添削とかさせれば、ニュアンス踏まえて指摘してくれますよ! 今回は、WPFにおいてViewとViewModelだけを使った、極めてシンプルな多言語対応サンプルを示したいと思います。 プロジェクト作成 今回は「WPFアプリケーション」で MultiLanguageTest というプロジェクトを作りましょう。フレームワークは「.NET 9.0」を使用します。 そして開かれた MainWindow.xaml を以下のようにしましょう。 「Language」の中に「Japanese」「English」「Russian」として、ウィンドウ内全域にボタンを貼り付けているだけです。 <Window x:Class="MultiLanguageTest.MainWindow" 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:MultiLanguageTest" mc:Ignorable="d" Title="MultiLanguageTest" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Menu> <MenuItem Header="Language"> <MenuItem Header="Japanese" Command="{Binding ToJapanese}"/> <MenuItem Header="English" Command="{Binding ToEnglish}"/> <MenuItem Header="Russian" Command="{Binding ToRussian}"/> </MenuItem> </Menu> <Button Grid.Row="1" Margin="5" Content="{Binding Greetings}" Command="{Binding ExecuteGreetings}"/> </Grid> </Window> シンプルなテストなので、UIに関しては最低限の実装になっています。画面とかは本題じゃないからいいよね? 下準備に CommunityToolkit.Mvvm の導入 利便性のため、NuGetで CommunityToolkit.Mvvm を導入します。 メニューの「ツール」-「NuGetパッケージマネージャ」-「ソリューションのNuGetパッケージの管理」から、 「参照」タブをクリックして CommunityToolkit.Mvvm を検索してプロジェクトにインストールします。 ライセンスが不安かも知れませんが CommunityToolkit.Mvvm はMITライセンスという、オープンソースライセンスの中で最も緩いライセンスです。 CommunityToolkit.Mvvm 自体を配布しないのであれば、商用とかクローズドソースもOKなので心配は要らないでしょう。 ほら、あの Xamarin で使われていた(もう過去形なんだよな…) Mono と同じライセンスです。 っていうか、これは CommunityToolkit.Mvvm 覚え書きに書くべき内容だったか…? 自分の目で確認したい方は.NET Community Toolkitをどうぞ。 ...

2024年11月12日 · (2025年06月19日 更新) · 3 分 · ☨もりゃき.xyz☨