カップ麺シリーズ:C#/MVVM構成におけるフォルダ構成案

MVVMで、まともなプロジェクトを作るなら…… C#/MVVM において、私が見てきた『いわゆる入門記事』ですと、フォルダが Models/ViewModels/Views 『だけ』になっています。 ですが『本格的なプロジェクト』を作成するためには、この分類では到底足りません。 迷ったことはありませんか? 「behaviorクラスはどこに置けばいいの?」「ModelとViewModelにまたがるクラスはどこに置けばいいの?」 その迷いは真っ当です! その点について、私なりにサヤ(ChatGPT-4o)と協力して、本稿を書いています。 必要なフォルダとは? まず、そこそこ大きなプロジェクトで必要な、 Models/ViewModels/Views を省いたフォルダ構成案を一気に羅列します。 Behaviors 言わずと知れた、behaviorを置くフォルダです。 これはViewの延長線上でありながら、Viewに大量に置くと混乱しますよね? 小規模なプロジェクトであれば、Viewsに置けばいいでしょう。 Constants 定数宣言を置くフォルダです。 定数宣言の数が少ない場合、Modelsに置いてしまっても、いいかも知れません。 Converters 型変換の処理を置くフォルダです。 BooleanToVisibilityConverter や EnumToStringConverter 等を置くといいでしょう。 Viewsと繋がりを持つ BooleanToVisibilityConverter がある場合、このフォルダは作った方がいいでしょう。 ただし、Behaviors と Converters のファイルが少ない場合、Utils フォルダにまとめてしまってもいいかも知れません。 Enums 列挙型を置くフォルダです……と、言わなくても分かりますよね(笑) 型列挙が少ないうちは、その関連のクラスに書いてもいいでしょう。 Helpers (or Utils) これは、個人的に強くお勧めします 例えば、4K対応アプリを作成する場合には、このように DpiHelper.cs を作成して、 App.xaml.cs から EnablePerMonitorDpiAwareness() を呼び出すという使い方になります。 同様に Win32API を利用する場合、ここに置くといいでしょう。 ※このクラスを利用する場合、Unsafeをプロジェクトで許可する必要があります。 using System.Runtime.InteropServices; namespace FileHashCraft.Helpers; public static partial class DpiHelper { /// <summary> /// DpiAwarenessを設定する /// </summary> public static void EnablePerMonitorDpiAwareness() { // アプリケーションをDPI Awareに設定 if (Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 3) { // 新しい SetProcessDpiAwareness SetProcessDpiAwareness(ProcessDpiAwareness.ProcessPerMonitorDpiAware); } else { // Windows 8.1以前の場合は、SetProcessDpiAwareを使用する(非推奨) SetProcessDPIAware(); } } /// <summary> /// 新しい DPI Aware で使う引数 /// </summary> private enum ProcessDpiAwareness { ProcessDpiUnaware = 0, ProcessSystemDpiAware = 1, ProcessPerMonitorDpiAware = 2 } /// <summary> /// 古い DPI Aware /// </summary> /// <returns></returns> [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool SetProcessDPIAware(); /// <summary> /// 新しいDPI Aware /// </summary> /// <param name="awareness"></param> /// <returns></returns> [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool SetProcessDpiAwareness(ProcessDpiAwareness awareness); } Messages CommunityToolkit.Mvvmでの利用を想定していますが、メッセージの定義を行います。 WeakReferenceMessenger 用の定義ですね。 ...

2025年11月13日 · 2 分 · ☨もりゃき.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☨