mvvmmvvmを使い始める


備考

このセクションでは、mvvmの概要と、開発者がmvvmを使用する理由について概説します。

また、mvvm内の大きなテーマについても言及し、関連するトピックにリンクする必要があります。 mvvmのドキュメントは新しくなっているので、それらの関連トピックの初期バージョンを作成する必要があります。

C#MVVMまとめと完全な例

概要:

MVVMは、 モデルビュー 、およびViewModelという3つの異なるコンポーネントによって表されるアーキテクチャパターンです。これらの3つの層を理解するためには、各層を簡単に定義し、それらがどのように連動するかについて説明する必要があります。

モデルとは、ビジネスロジックを駆動するレイヤーです。 ViewModelで消費するために、任意のデータソースから情報を取得して格納します。

ViewModelは、 ビューモデルの間のブリッジとして機能するレイヤーです。 Modelからの生データをViewの表示可能な形式に変換する場合と変換しない場合があります 。変換の例は、モデルからブール値のフラグ(TrueまたはFalse)です。

ビューは、ソフトウェアのインターフェース(つまりGUI)を表すレイヤーです。その役割は、 ViewModel からの情報ユーザに表示し、情報の変更をViewModelに返信することです。

これらの3つのコンポーネントは、次のように相互に参照することによって一緒に機能します。

  • ビューViewModelを参照します。
  • ViewModelモデルを参照します。

ViewViewModelデータバインディングと呼ばれる双方向通信が可能であることに注意することが重要です。

双方向通信(データバインディング)の主要な要素は、 INotifyPropertyChangedインターフェイスです

この仕組みを利用することで、Viewは 、ユーザ入力を介してのViewModel内のデータを変更することができ、かつViewModelには、 モデル内またはリポジトリから更新されたデータとプロセスを介して更新されている可能性があり、データとビューを更新することができます。

MVVMアーキテクチャーは、これらの層のそれぞれについての分離の分離に重点を置いています。レイヤーを分離すると、次のような利点があります。

  • モジュラリティ:各レイヤの内部実装は、他のレイヤに影響を与えずに変更またはスワップできます。
  • テスト容易性の向上: ViewModelのコードがビューのコードビハインドで記述されている場合は不可能な、偽のデータで各レイヤーをユニットテストすることができます

ビルド:

新しいWPFアプリケーションプロジェクトを作成する新しいWPFアプリケーションプロジェクトを作成する

ソリューション内に3つの新しいフォルダ( モデルViewModelView )を作成し、元のMainWindow.xaml を削除して、新しいスタートを得るだけです。

ソリューションに3つの新しいフォルダを作成する

別々のレイヤーにそれぞれ対応する3つの新しいアイテムを作成します。

  • モデルフォルダを右クリックし、 HelloWorldModel.cs というクラスアイテムを追加します。
  • ViewModelフォルダを右クリックし、 HelloWorldViewModel.cs というクラスアイテムを追加します。
  • Viewフォルダを右クリックし、 HelloWorldView.xaml というウィンドウ(WPF)アイテムを追加します。

3つの項目を追加する

新しいビューをポイントするようにApp.xamlApp.xaml する

<Application x:Class="MyMVVMProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MyMVVMProject"
             StartupUri="/View/HelloWorldView.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>
 

ViewModel:

最初にViewModelを構築します。クラスは、 INotifyPropertyChanged インターフェイスを実装し、 PropertyChangedEventHandler イベントを宣言し、イベントを発生させるメソッドを作成する必要があります(ソース: MSDN:プロパティ変更通知を実装する方法 )。次に、フィールドと対応するプロパティを宣言し、プロパティのset アクセサでOnPropertyChanged() メソッドをOnPropertyChanged() ことを確認します。以下の例のコンストラクタは、 モデルViewModelにデータを提供することを示すために使用されています。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using MyMVVMProject.Model;

namespace MyMVVMProject.ViewModel
{
    // Implements INotifyPropertyChanged interface to support bindings
    public class HelloWorldViewModel : INotifyPropertyChanged
    {
        private string helloString;

        public event PropertyChangedEventHandler PropertyChanged;

        public string HelloString
        {
            get
            {
                return helloString;
            }
            set
            {
                helloString = value;
                OnPropertyChanged();
            }
        }

        /// <summary>
        /// Raises OnPropertychangedEvent when property changes
        /// </summary>
        /// <param name="name">String representing the property name</param>
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public HelloWorldViewModel()
        {
            HelloWorldModel helloWorldModel = new HelloWorldModel();
            helloString = helloWorldModel.ImportantInfo;
        }
    }
}
 

モデル:

次に、 モデルを構築します。前述のように、 モデルViewModelのデータをリポジトリから取得し(保存するためにリポジトリに戻すだけでなく)、リポジトリから取得します。以下では、単純なList<string> を返すGetData() メソッドをGetData() して説明します。ビジネスロジックもこのレイヤーに適用され、 ConcatenateData() メソッドで見ることができます。このメソッドは、以前に "リポジトリ"から返されたList<string> から "Hello、world!"という文を作成します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyMVVMProject.Model
{
    public class HelloWorldModel
    {
        private List<string> repositoryData;
        public string ImportantInfo
        {
            get
            {
                return ConcatenateData(repositoryData);
            }
        }

        public HelloWorldModel()
        {
            repositoryData = GetData();
        }

        /// <summary>
        /// Simulates data retrieval from a repository
        /// </summary>
        /// <returns>List of strings</returns>
        private List<string> GetData()
        {
            repositoryData = new List<string>()
            {
                "Hello",
                "world"
            };
            return repositoryData;
        }

        /// <summary>
        /// Concatenate the information from the list into a fully formed sentence.
        /// </summary>
        /// <returns>A string</returns>
        private string ConcatenateData(List<string> dataList)
        {
            string importantInfo = dataList.ElementAt(0) + ", " + dataList.ElementAt(1) + "!";
            return importantInfo;
        }
    }
}
 

表示:

最後に、 ビューを構築することができます。この例では、コードの後ろに追加する必要はありませんが、アプリケーションのニーズによって異なる場合があります。ただし、XAMLにはいくつかの行が追加されています。 Window は、 ViewModel 名前空間への参照が必要です。これは、XAML名前空間xmlns:vm="clr-namespace:MyMVVMProject.ViewModel" マップされます。次に、WindowにはDataContext が必要です。これは<vm:HelloWorldViewModel/> 設定されています。これで、ラベル(または選択したコントロール)をウィンドウに追加できます。この段階のポイントは、ラベルコンテンツとして表示するViewModelのプロパティにBindingを設定することです。この場合、 {Binding HelloString} です。

以来、後者の場合にはビューは 、値が変更通知を受信しませんように、フィールドプロパティにバインドすることが重要ではなく、 OnPropertyChanged() メソッドのみ発生しますPropertyChangedEvent 性質上、およびありませんでフィールド。

<Window x:Class="MyMVVMProject.View.HelloWorldView"
        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:local="clr-namespace:MyMVVMProject.View"
        xmlns:vm="clr-namespace:MyMVVMProject.ViewModel"
        mc:Ignorable="d"
        Title="HelloWorldView" Height="300" Width="300">
    <Window.DataContext>
        <vm:HelloWorldViewModel/>
    </Window.DataContext>
    <Grid>
        <Label x:Name="label" FontSize="30" Content="{Binding HelloString}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>