Model→View
まずは簡単なModel→Viewから。CounterViewModel.hを示します:
// CounterViewModel.h
#pragma once
#include "Common/BindableBase.h" // Common::BindableBase
#include "CounterLib/CounterLib.h" // Counterlib::Counter
#include <memory> // std::uniqur_ptr
namespace CounterApp {
[Windows::UI::Xaml::Data::Bindable]
public ref class CounterViewModel sealed : Common::BindableBase {
public:
CounterViewModel();
// properties
property int Count { int get(); }
void increment();
void decrement();
private:
std::unique_ptr<CounterLib::Counter> counter_;
};
}
- アトリビュート:[Windows::UI::Xaml::Data::Bindable]をつけること
- Common::BindableBaseから導出すること
がここでの定石です。
int型のプロパティ:Countを定義しました。Viewがこのプロパティを読み取ってTextBlockに表示するよう仕向けます。
CounterViewmodel.cppはこんな感じ:
// CounterViewModel.cpp
#include "pch.h"
#include "CounterViewModel.h"
using namespace Platform;
using namespace Windows::UI::Xaml::Input;
namespace CounterApp {
CounterViewModel::CounterViewModel() : counter_(new CounterLib::DefaultCounter(0)) {}
// properties
int CounterViewModel::Count::get() { return counter_->get(); }
void CounterViewModel::increment() {
counter_->increment();
OnPropertyChanged(L"Count");
}
void CounterViewModel::decrement() {
counter_->decrement();
OnPropertyChanged(L"Count");
}
}
increment()/decrement()内でOnPropertyChanged(L"Count")することで「Countプロパティが変更された」ことをViewに伝え、Viewはそれを契機にCountを読み取ります。ViewすなわちMainPage.xamlの変更点は1つだけ、<TextBlock>要素にText="{Binding Count}"を追加し、TextBlockのTextをCountプロパティに紐づけます。
MainPage.xamlのコード・ビハインドはこのようになります。
// MainPage.xaml.h (step-1)
// MainPage クラスの宣言
//
#pragma once
#include "Common\LayoutAwarePage.h" // 生成されたヘッダーによって要求されます
#include "MainPage.g.h"
#include "CounterViewModel.h" // 追加
namespace CounterApp
{
/// <summary>
/// 多くのアプリケーションに共通の特性を指定する基本ページ。
/// </summary>
public ref class MainPage sealed
{
public:
MainPage();
protected:
virtual void LoadState(Platform::Object^ navigationParameter,
Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ pageState) override;
virtual void SaveState(Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ pageState) override;
private:
void btnInc_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void btnDec_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
CounterViewModel model_; // 追加
};
}
// MainPage.xaml.cpp (step-1)
// MainPage クラスの実装
...
MainPage::MainPage()
{
InitializeComponent();
CounterPage->DataContext = %model_; // 追加
}
...
void CounterApp::MainPage::btnInc_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
model_.increment();
}
void CounterApp::MainPage::btnDec_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
model_.decrement();
}
コンストラクタでバインドする相手(プロパティを読み出す先)となるCounterViewModelを設定しています。ボタンのイベント・ハンドラからはTextBlockのTextを更新する処理が消え、単にincrement/decrementするだけになりました。

