はじめに
この記事は、初心者向けではありません。 WPFにおける、CommunityToolkit.Mvvmを使って「最低限の」環境を作るための、私的なメモにすぎません。
ここでのプロジェクト名は Memoir とします。プロジェクトはWPFの最新.NET(記述時点では10.0)にします。
プロジェクト作成
NuGetでインストールする必要があるパッケージ
- CommunityToolkit.Mvvm
- Microsoft.Extensions.DependencyInjection
まずは Views,ViewModels,Models,Helpers フォルダを作り、MainWindow.xaml を Views に移動する。
そして App.xaml を以下のようにする(StartupUriにViewsを追加する)。
<Application x:Class="Memoir.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Memoir"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
4K対応
このコードを通すためには、unsafe の許可を通さなければならない。
プロジェクトで「ビルド」-「アンセーフ コード」のチェックボックスにチェックを付けること。
Helpers ディレクトリに以下のファイル DpiHelper.cs を作成する。
namespace Memoir.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);
}
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();
}
}
データバインディング
次に ViewModels\MainWindowViewModel.cs を作成して以下の内容にする。
namespace Memoir.ViewModels;
public interface IMainWindowViewModel { }
public class MainWindowViewModel : IMainWindowViewModel
{
}
ここで App.xaml.cs に以下を追記する
using Memoir.ViewModels;
ウィンドウのタイトル名を変えるなら、MainWindow.xaml で直接「MainWindow」を書き換えるか、データバインディングすること。
MainWindow.xaml.cs をこうする。
using System.Windows;
using CommunityToolkit.Mvvm.DependencyInjection;
using Memoir.ViewModels;
namespace Memoir;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = Ioc.Default.GetService<IMainWindowViewModel>();
}
}