Silverlight-view-model
Silverlight-ビューモデル
この章では、Silverlightのソフトウェア開発における重要な手法である View Models を使用します。
- * viewモデル*は重要な要素であり、ビューをモデルから分離することにより、分離表示と呼ばれる手法を導入します。
- View Models は、分離されたプレゼンテーションの一方向を実現します。Silverlightのデータバインディングを利用して、ユーザーインターフェイスで必要なコードの量を削減する方法を説明します。
UI開発の課題
*View Models* は、ユーザーインターフェイスソフトウェアの開発時に頻繁に発生する特定の問題を解決するように設計されています。 おそらく最も重要なことは、特に自動化された単体テストでは、ユーザーインターフェイスコードを複雑にテストすることが難しい場合が多いことです。 コードの継続的な柔軟性と保守性に影響を与える可能性があるコード品質の問題もあります。
- Visual Studioの設計ツールがあなたを導いてくれる最小の抵抗の道をたどると、コードビハインドにあまりにも多くのコードを入れることになってしまいます。
- 大量のアプリケーション機能がコードビハインドに追加されるのを見るのは非常に一般的です。
- ビジネスロジックをユーザーインターフェイスクラスに入れることを実際に計画している開発者はほとんどいませんが、Visual Studioがイベントハンドラーを配置する場所であるため、物事を成し遂げるには非常に便利な場所になります。
- クラスの責任が明確に定義され、合理的に狭い場合、ソフトウェアの開発と保守が容易になることは広く受け入れられています。
- コードビハインドの仕事は、必要なユーザーインターフェイスを構成するオブジェクトと直接対話することです。
- 問題を引き起こす傾向があるアプリケーションの動作を決定するコードを配置するとすぐに。
- アプリケーションロジックは、ユーザーインターフェイスに関係するコードに流れ込むだけでなく、一部の開発者は重要なアプリケーションの状態を保持するためにコントロールや他のユーザーインターフェイスオブジェクトに依存し始めます。
- モデルは単にデータを保持し、ビューはフォーマットされた日付を保持し、コントローラー(ViewModel)は2つの間の連絡役として機能します。 コントローラーは、ビューから入力を取得してモデルに配置したり、その逆を行ったりする場合があります。
分離プレゼンテーション
コードビハインドまたはXAMLにアプリケーションロジックを配置することによって生じる問題を回避するには、 separated presentation と呼ばれる手法を使用するのが最適です。 ユーザーインターフェイスオブジェクトを直接操作するために最低限必要なXAMLとコードビハインドがあるため、ユーザーインターフェイスクラスには、以下の左側に示すように、複雑な対話動作、アプリケーションロジック、その他すべてのコードも含まれます。
分離プレゼンテーションの重要な機能-
- 分離されたプレゼンテーションでは、ユーザーインターフェイスクラスがはるかに簡単です。 もちろんXAMLがありますが、コードビハインドは実用的ではありません。
- アプリケーションロジックは別のクラスに属します。これは、多くの場合 model と呼ばれます。
- 多くの開発者は、データバインディングを使用して、XAMLの要素をモデルのプロパティに直接接続しようとします。
- 問題は、*モデル*は、ユーザーがアプリケーションとどのように対話するかではなく、アプリケーションが何をするかという問題に完全に関係していることです。
- ほとんどのユーザーインターフェイスには、アプリケーションモデルに属さない状態があります。 たとえば、ユーザーインターフェイスでドラッグアンドドロップを使用している場合、ドラッグ中のアイテムが現在どこにあるか、可能なドロップターゲット上を移動するときに外観がどのように変化するか、ドロップターゲットがどのようになり得るかなどを追跡する必要がありますアイテムがそれらの上にドラッグされると変化します。
- この種の状態は驚くほど複雑になる可能性があるため、徹底的にテストする必要があります。
- 実際には、通常、ユーザーインターフェイスとモデルの間に他のクラスを配置する必要があります。 これには2つの重要な役割があります。
- まず、アプリケーションモデルを特定のユーザーインターフェイスビューに適合させます。
- 第二に、それは重要な相互作用ロジックが存在する場所であり、それによって、ユーザーインターフェイスを希望どおりに動作させるために必要なコードを意味します。
モデル/ビュー/ViewModel
*View Model* は、分離されたプレゼンテーションアプローチの例ですが、各レイヤーにどのような種類があるかを明確にしましょう。 3つの層があります-
- モデル
- View
- ViewModel
モデル
これは、ユーザーインターフェイスと直接関係のない通常のC#クラスで構成される*クラシック*オブジェクトモデルです。
通常、モデルコードは、ユーザーインターフェイスライブラリへの参照なしでコンパイルできると予想されます。 実際、まったく同じソースコードを取得して、Silverlightアプリケーション、通常の.NETコンソールアプリケーション、またはサーバー側のWebコードにコンパイルすることができるでしょう。
モデルのタイプは、アプリケーションが機能する概念を表す必要があります。
View
通常、ビューはUserControlであり、MainPageである場合も、ページの一部である場合もあります。
ほとんどのSilverlightアプリケーションでは、ユーザーインターフェイスを、ユーザーコントロールを定義する小さな部分に分割するか、各部分のビューを作成することをお勧めします。
Silverlightアプリケーションは、この点でユニークではありません。 明らかにSilverlight固有のものは、ビューです。 ユーザーインターフェイスがきめ細かくなればなるほど、より良いものになる傾向があります。 同じファイルで作業している他の開発者をすり減る可能性が低いだけでなく、物事を小さくシンプルに保つことで、スパゲッティのようなコードにつながるショートカットを自然に思いとどまらせることができます。
たとえば、リスト内の個々のアイテムを表す View を定義することは非常に一般的です。
ViewModel
最後に、 View ごとに ViewModel を記述します。 したがって、これは ViewModel クラスの重要な機能の1つです。
特定のビューを提供するために存在します。 ViewModel は、リストに表示される特定のデータ項目など、物事を提示する特定の方法に特化しています。
これが ViewModel と呼ばれる理由です。特に特定のビューに対して基礎となるモデルを適合させます。 モデルと同様に、 ViewModel も通常のC#クラスです。 特定のタイプから派生する必要はありません。
たまたま、一部の開発者は、いくつかの共通機能を基本ViewModelクラスに入れるのが便利だと感じていますが、パターンはそれを要求しません。 特に、 ViewModel は、Silverlight固有のタイプから派生しません。 ただし、モデルとは異なり、プロパティでSilverlightタイプを使用できます。
たとえば、ViewModelは、特定の条件下でのみユーザーインターフェイスの特定の部分を表示することを選択する可能性があるため、System.Windows.Visibility型のプロパティを提供できます。これは、Silverlight要素がVisibilityプロパティに使用する型です。 これにより、パネルなどの要素の可視性をViewModelに直接バインドできます。
例
- Model-View-ViewModel(MVVM)*アプローチを使用する簡単な例を見てみましょう。
ステップ1 *-新しいSilverlightアプリケーションプロジェクト *SilverlightMVVMDemo を作成します。
- ステップ2 *-以下に示すように、プロジェクトに3つのフォルダー(Model、ViewModel、およびViews)を追加します。
- ステップ3 *-ModelフォルダーにStudentModelクラスを追加し、そのクラスに以下のコードを貼り付けます。
using System.ComponentModel;
namespace SilverlightMVVMDemo.Model {
public class StudentModel {}
public class Student : INotifyPropertyChanged {
private string firstName;
private string lastName;
public string FirstName {
get { return firstName; }
set {
if (firstName != value) {
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
}
public string LastName {
get { return lastName; }
set {
if (lastName != value) {
lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
}
public string FullName {
get {
return firstName + " " + lastName;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
- ステップ4 *-別のStudentViewModelクラスをViewModelフォルダーに追加し、次のコードを貼り付けます。
using SilverlightMVVMDemo.Model;
using System.Collections.ObjectModel;
namespace SilverlightMVVMDemo.ViewModel {
public class StudentViewModel {
public ObservableCollection<Student> Students {
get;
set;
}
public void LoadStudents() {
ObservableCollection<Student> students = new ObservableCollection<Student>();
students.Add(new Student { FirstName = "Mark", LastName = "Allain" });
students.Add(new Student { FirstName = "Allen", LastName = "Brown" });
students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" });
Students = students;
}
}
}
ステップ5 *- *Views フォルダーを右クリックして Silverlight User Control を追加し、* Add New Item…*を選択します。
ステップ6 *-[追加]をクリックします。 これで、XAMLファイルが表示されます。 さまざまなUI要素を含む *StudentView.xaml ファイルに次のコードを追加します。
<UserControl x:Class = "SilverlightMVVMDemo.Views.StudentView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable = "d"
d:DesignHeight = "300" d:DesignWidth = "400">
<Grid x:Name = "LayoutRoot" Background = "White">
<StackPanel HorizontalAlignment = "Left">
<ItemsControl ItemsSource = "{Binding Path=Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"
Width = "100" Margin = "3 5 3 5"/>
<TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"
Width = "100" Margin = "0 5 3 5"/>
<TextBlock Text = "{Binding Path = FullName, Mode=OneWay}"
Margin = "0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
ステップ7 *-次に示すように、 *StudentView を MainPage.xaml ファイルに追加します。
<UserControl x:Class = "SilverlightMVVMDemo.MainPage"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views = "clr-namespace:SilverlightMVVMDemo.Views"
mc:Ignorable = "d"
d:DesignHeight = "576.316" d:DesignWidth = "863.158">
<Grid x:Name = "LayoutRoot" Background = "White">
<views:StudentView x:Name = "StudentViewControl" Loaded = "StudentViewControl_Loaded"/>
</Grid>
</UserControl>
ステップ8 *- *ViewModel から View を更新する MainPage.xaml.cs ファイルの Loaded イベントの実装です。
using System.Windows;
using System.Windows.Controls;
namespace SilverlightMVVMDemo {
public partial class MainPage : UserControl {
public MainPage() {
InitializeComponent();
}
}
private void StudentViewControl_Loaded(object sender, RoutedEventArgs e) {
SilverlightMVVMDemo.ViewModel.StudentViewModel
studentViewModelObject = new SilverlightMVVMDemo.ViewModel.
StudentViewModel();
studentViewModelObject.LoadStudents();
StudentViewControl.DataContext = studentViewModelObject;
}
}
- ステップ9 *-上記のコードをコンパイルして実行すると、次の出力がWebページに表示されます。
UI vs ViewModel
MVVMアプローチの最も難しい部分の1つは、境界線がどこに来るかを見つけることです。 どのものがどこに属しているかは必ずしも明らかではありません。
- 特に、一部のユーザーインターフェイス要素は機能を提供します。厳密なビューによれば、これは間違いなくViewModelに属している必要があります。
- 一般に、 View に実装されているすべての動作が ViewModel に適しているわけではありません。
- この理由の一部は、特にVisual StudioやBlendなどの設計環境を使用する場合を除き、ViewModelの動作を再利用のためにパッケージ化する標準的な方法がないことです。
MVVMの利点
MVVMには次の利点があります-
- プレゼンテーションの懸念の分離(View、ViewModel、Model)
- テスト可能で管理しやすいコードをきれいにします。 単体テストにプレゼンテーション層のロジックを含めることができます。
- コードの背後にあるコードがないため、プレゼンテーション層とロジックは疎結合です。
- データバインディングのより良い方法。
MVVMの欠点
シンプルなUIの場合、MVVMはやり過ぎになる可能性があります。 複雑なデータバインディングがある場合、デバッグは少し難しくなります。