UWPアプリをMVVMで作成するときに最初にやること
C#でUWPアプリケーションを新しく作成するときにまずやることをここに残しておきます。
※Visual Studio 2017を前提にしています。
Visual Studio でプロジェクトの新規作成
空のプロジェクトを作成
メニューからプロジェクトを新規作成。
空白のアプリ(ユニバーサルWindows)を選んで保存場所を選びます。
コンパイルするターゲットとなるバージョンと、使うAPIに応じて最小バージョンを適当に選びます。
作成直後はこのようなフォルダ構造になっています。
プロジェクト作成直後にやること
MVVMとローカライズ用のフォルダを作成
作成するフォルダは以下の5つ
- Models
- Views
- ViewModels
- Strings
- Strings\ja-jp
上3つはMVVM用、下2つはローカライズ用です。ローカライズ用フォルダは、言語に応じて増やしていきます。
詳しくは「UI 文字列をリソースに格納する」を参考に。
MainPageをViewsフォルダに移動
プロジェクトに最初から含まれているMainPageをViewsフォルダに移動していきます。ここでは以下の作業をします。
- MainPage.xaml,MainPage.xaml.csファイルを移動
- MainPageクラスの名前空間を修正
MainPage.xaml,MainPage.xaml.csファイルを移動
MainPage.xamlをドラッグ&ドロップでViewsフォルダに持っていきます。これで、コードビハインドであるMainPage.xaml.csも一緒にViewsフォルダに入ります。
MainPageクラスの名前空間を修正
MainPageクラスは、最初はプロジェクト名と同じ名前空間の直下に配置されます。これをViewsフォルダに入れててもコンパイルできるように、Views名前空間に移動します。
修正する場所は、MainPage.xamlとMainPage.xaml.cs、忘れていけないのがApp.xaml.csの最初に表示するページを指定するところです。
1つ目はMainPage.xamlのx:Class
2つ目はMainPage.xaml.csのMainPageクラスがあるnamespace
3つ目はApp.xaml.csのOnLaunched関数の中にあるNavigateの引数
MainPage.xamlを直すついでに、xamlタグ内で用いる名前空間にviewsとviewmodelsを追加しておくと便利です。
ViewModelの作成
MainPageをViewsに移動したら、これに対応するViewModelを作成します。
ViewModel用に補助クラスの作成
ViewModelからView, ModelからViewへプロパティの変更を知らせるために、INotifyPropertyChangedを頻繁に使うため、これを実装したクラスを用意しておくと継承だけで使うことができて便利です。
先人の知恵「Observable.cs」を利用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using System; using System.ComponentModel; using System.Runtime.CompilerServices; // https://github.com/Microsoft/WindowsTemplateStudio/blob/master/templates/_composition/MVVMBasic/Project/Helpers/Observable.cs から引用 // 名前空間を修正 namespace App8.Helpers { public class Observable : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) { if (Equals(storage, value)) { return; } storage = value; OnPropertyChanged(propertyName); } protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } |
MainPageViewModel.csの作成
Observable.csをもとに、MainPageに対応するViewModelクラスを作成します。初期化関数にViewを渡せるようにしておいて、ViewModelからViewを弄れるようにしておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
namespace App8.ViewModels { public class MainPageViewModel : Helpers.Observable { public Views.MainPage View { get; private set; } = null; public void Initialize(Views.MainPage mainPage) { View = mainPage; } } } |
MainPage.xaml.csの修正
MainPageViewModelクラスとの対応を入れます。具体的にはプロパティの追加、ViewModelの初期化コードの呼び出し、データコンテキストの紐づけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using Windows.UI.Xaml.Controls; // 空白ページの項目テンプレートについては、https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x411 を参照してください namespace App8.Views { /// <summary> /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。 /// </summary> public sealed partial class MainPage : Page { public ViewModels.MainPageViewModel ViewModel { get; private set; } = new ViewModels.MainPageViewModel(); public MainPage() { this.InitializeComponent(); ViewModel.Initialize(this); this.DataContext = ViewModel; } } } |
多言語化(ローカライズ)
Stringsリソース
補助クラス
文字列はローカライズ文字列を取得するための拡張メソッドを作っておくと便利です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using System; using System.Runtime.InteropServices; using Windows.ApplicationModel.Resources; // https://github.com/Microsoft/WindowsTemplateStudio/blob/master/templates/Projects/Default/Helpers/ResourceExtensions.cs から引用 // 名前空間を修正 namespace App8.Helpers { internal static class ResourceExtensions { private static ResourceLoader _resLoader = new ResourceLoader(); public static string GetLocalized(this string resourceKey) { return _resLoader.GetString(resourceKey); } } } |
余談
毎回やるのは地味に面倒なので、Microsoftの素晴らしいテンプレート「Windows Template Studio」を使う手もあります。高機能なので、コードが複雑になりますが、Master-Detailや設定画面などを最初から作れるので便利です。
ディスカッション
コメント一覧
まだ、コメントがありません