カップ麺シリーズ: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 用の定義ですね。 ...