こんにちは、ゆたんぽです。
前回に引き続き、今回は「Prism」の使用に欠かせない、データバインドについて記事にしていこうと思います。
今回もよろしくお願いします。
データバインドとは
データバインドとは、「ViewとViewModelのデータを同期する」方法です。
前回の記事でも述べましたが、MVVMモデルでは、Viewは画面であり、ViewModelは、画面の状態を編集(制御)するものです。
WindowsのFormアプリケーションでは、画面のコードビハインド(画面の後ろにあるプログラム)で、画面のテキストなどを編集できました。しかし、MVVMモデルでは、ViewModelへ記述したほうが、「コードのテストが容易」になり、「他のソフトへの汎用性」も確保されます。
私も最初は、コードビハインドのほうが断然わかりやすかったのですが、現在は慣れてきていますし、上記の利点からViewModelへの記述が良いと感じています。
データバインドの基本
前回までに作成したプロジェクトで、すでにコードビハインドの基本が記述されています。
「MainWindow.xaml」と「MainWindowViewModel.cs」を確認してみましょう。
<Window x:Class="Sample.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
まずは、「MainWindow.xaml」を確認していきます。上記のプログラム6行目にある「Title=”{Binding Title}”」がコードバインディングの記述方法になります。
この意味は、「アプリケーションのタイトルに、”Title”という変数をバインドする」というものです。
つまり、MainWindowViewModelで記載されている、Titleという変数の値(文字)が変わると、アプリケーションのタイトルも変更されるということです。
ちなみにアプリケーションのタイトルは以下の赤枠部分になります。
using Prism.Mvvm;
namespace Sample.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainWindowViewModel()
{
}
}
}
続いて、「MainWindowViewModel」を確認してみます。
MainWindow.xamlでバインディングした「Title」が、String型で定義されています。
このようにViewModel側で、名前を同一に定義することでバインディングをすることができ、値が連動します。
試しに名前を7行目で定義されている”Prism Application”を ”Sample Application” に変更してみてください。
using Prism.Mvvm;
namespace Sample.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Sample Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainWindowViewModel()
{
}
}
}
下記のように、名前が変更されていることが確認できるでしょう。
ラベルのデータバインド
続いて、テキストブロックのデータバインディングを実装してみます。
まずは、バインディング関係なく、テキストブロックを追加してみましょう。
以下のように、「MainWindow.xaml」に「<Label Content=”システム日時”/>」と入力してください。
<Window x:Class="Sample.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<Label Content="システム日時"/>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
この状態で起動すると以下のように、画面にシステム日時が表示されます。
次に、バインディングするLabelを作成します。以下のようにラベルを追加してください。
<Window x:Class="Sample.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525"
WindowStartupLocation="CenterScreen"><!--←追加行-->
<Grid>
<StackPanel>
<Label Content="システム日時"/>
<Label Content="{Binding SystemData}"/>
</StackPanel>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
StackPanelは、< StackPanel ></ StackPanel >で囲んだ部分を重ならないように自動で順番に表示するようにしてくれます。初期状態では、縦に並びます。よく使うので覚えておきましょう。
次に「MainWondowViewModel.cs」にバインディングする変数を定義していきましょう。
以下のように「SystemDate」を追加してください。
using Prism.Mvvm;
using System;
namespace Sample.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Sample Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private string _systemData = DateTime.Now.ToString("yyyy年MM月dd日 HH時mm分ss秒");
public string SystemData
{
get { return _systemData; }
set { SetProperty(ref _systemData, value); }
}
public MainWindowViewModel()
{
}
}
}
簡単に解説していきます。
「DateTime.Now.ToString(“yyyy年MM月dd日 HH時mm分ss秒”);」で、現在時刻を変数に格納しています。
DateTime.Nowは、using Systemを入れることで使用できます。 Tostringでstring型へ変換しています。
次に、(“yyyy年MM月dd日 HH時mm分ss秒”)の部分で、 DateTime.Nowで取得した時間の表記を修正しています。
Setpropertyは、値が代入された際にview側へ変更を通知する役割を担っています。
それぞれわからないがあれば、ウェブで検索してみるとすぐに見つかると思いますので確認してみてください。
この状態でデバッグを実行すると以下の画面のようになります。
ボタンのデータバインディング
次にボタンのデータバインディングについて説明していきます。
WindowsFormでは、コードビハインドにクリックイベントが用意されていました。
MVVMモデルでは、前に述べたようにテストの容易性などから、ボタンのイベントもViewModelへ記述することが推奨されているため、ボタンにもデータバインディングが必要になります。
それでは、さっそく記述してみましょう。まずは、MainWindow.xamlからです。
<Window x:Class="Sample.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<StackPanel>
<Label Content="システム日時"/>
<Label Content="{Binding SystemData}"/>
<Button Content="時間更新"
Command="{Binding UpdateButton}"/>
</StackPanel>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
上記で追記した部分について説明します。
<Button>は、そのままボタンを表しています。”<Button” と”/>”の間にボタンの文字や大きさ、色などが指定できます。
今回は、ボタンの文字を「時間更新」するために、Content=”時間更新”としています。””の間に任意の文字を入れることで、ボタンの文字を変更することができます。
「Command=”{Binding UpdateButton}”/>」は、データバインディング記載部分です。
前回のLabelと違う部分は、Content部分がCommandに代わっています。
このCommandは、ボタンが押された時のイベントと同じだと思って大丈夫です。
今回は、”UpdateButton”としたので、ViewModel側でも、データバインディングするために”UpdateButton”を定義します。
using Prism.Commands;
using Prism.Mvvm;
using System;
namespace Sample.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Sample Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private string _systemData = DateTime.Now.ToString("yyyy年MM月dd日 HH時mm分ss秒");
public string SystemData
{
get { return _systemData; }
set { SetProperty(ref _systemData, value); }
}
public DelegateCommand UpdateButton { get; }
public MainWindowViewModel()
{
UpdateButton = new DelegateCommand(UpdateButtonExe);
}
private void UpdateButtonExe()
{
SystemData = DateTime.Now.ToString("yyyy年MM月dd日 HH時mm分ss秒");
}
}
}
ViewModel側は上記のように追加しました。内容を説明していきます。
まず、データバインディングするために、”public DelegateCommand UpdateButton { get; }”を追加しました。
このDelegateCommandが、ボタンのデータバインディングに必要なものになります。
使用するために、1行目のように”using Prism.Commands;”を追加しましょう。
次に、コンストラクタで、「ボタンを押して時にどうする?」の記述をします。
その記述が、”UpdateButton = new DelegateCommand(UpdateButtonExe);”部分になります。
ここでは、先ほど定義した”UpdateButton”に、”UpdateButtonExe”という関数を紐づけること紐づけています。
ここで「ボタンを押したときに、”UpdateButtonExe”を起動する」ことを定義しています。
最後に、”UpdateButtonExe”部分を記述していきます。
”private void UpdateButtonExe()”の{}の中に、具体的に何をするか記述していきます。
今回は、SystemDateの時間をボタンを押した時間に更新するために、”SystemData = DateTime.Now.ToString(“yyyy年MM月dd日 HH時mm分ss秒”);”と記載しました。
これは、前回説明した部分と同じなので説明は不要だと思います。
この状態で一度デバッグを開始してみましょう。
それでは、ボタンを押してみてください。ボタンを押す度にシステム日時の部分がボタンを押した時間に変更されることがわかると思います。
以上のような手順でボタンのデータバインディングをすることができます。
まとめ&次回予告
本日は、データバインディングの基本を記事にしてきました。
ラベルとボタンともに、非常によく使う項目ですので覚えていきましょう。
ここまで来ると、自分で少し内容を変更することで、バインディングの基礎を確かめるのも良いと思います。
次回は、いよいよPrismの醍醐味である「画面遷移」について記事にしていこうと思います。
次回もよろしくお願いします。
4.Prismで画面遷移