MVVMパターンの実装ガイド

1. MVVMパターンの基本概念

MVVM(Model-View-ViewModel)は、プレゼンテーション層とビジネスロジックを分離するためのアーキテクチャパターンです。このパターン実装には、データバインディングコマンドパターンという2つの主要な技術が使用されます。

データバインディングの役割

データバインディングは、ViewとViewModel間の自動データ同期を可能にする機構です。ViewModelのプロパティ値が変更された場合、自動的にViewのUIが更新されます。これにより、手動でDOMやコントロールを更新する的必要性がなくなります。

コマンドパターンの役割

コマンドパターンは、ユーザーの操作をオブジェクトとして抽象化します。ボタンクリックやその他のユーザーインタラクションは、コマンドオブジェクトとしてViewModelに передаされます。これにより、UIロジックとビジネスロジックの分離が実現されます。

2. 実装サンプル

実践的な例:2つの数値を加算する計算機

以下に、WPFアプリケーションでのMVVM実装を示します。

ViewModel基本クラス

namespace SampleApp.ViewModels
{
    public abstract class BindableBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value))
                return false;

            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
}

メインViewModelクラス

namespace SampleApp.ViewModels
{
    public class CalculatorViewModel : BindableBase
    {
        private double _firstNumber;
        public double FirstNumber
        {
            get => _firstNumber;
            set => SetProperty(ref _firstNumber, value);
        }

        private double _secondNumber;
        public double SecondNumber
        {
            get => _secondNumber;
            set => SetProperty(ref _secondNumber, value);
        }

        private double _computedResult;
        public double ComputedResult
        {
            get => _computedResult;
            set => SetProperty(ref _computedResult, value);
        }

        public ICommand CalculateCommand { get; }

        public CalculatorViewModel()
        {
            CalculateCommand = new RelayCommand(ExecuteCalculation, CanExecuteCalculation);
        }

        private void ExecuteCalculation(object parameter)
        {
            ComputedResult = FirstNumber + SecondNumber;
        }

        private bool CanExecuteCalculation(object parameter)
        {
            return true;
        }
    }
}

コマンド実装クラス

namespace SampleApp.Commands
{
    public class RelayCommand : ICommand
    {
        private readonly Action<object> _executeMethod;
        private readonly Func<object, bool> _canExecuteMethod;

        public event EventHandler CanExecuteChanged
        {
            add => CommandManager.RequerySuggested += value;
            remove => CommandManager.RequerySuggested -= value;
        }

        public RelayCommand(Action<object> executeMethod, Func<object, bool> canExecuteMethod = null)
        {
            _executeMethod = executeMethod ?? throw new ArgumentNullException(nameof(executeMethod));
            _canExecuteMethod = canExecuteMethod;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecuteMethod == null || _canExecuteMethod(parameter);
        }

        public void Execute(object parameter)
        {
            _executeMethod(parameter);
        }
    }
}

3. 機能拡張:複数のインタラクション対応

単純なクリックイベントだけでなく、さまざまなユーザー操作にコマンドをバインドすることが可能です。以下のXAML例では、マウス関連のイベントにコマンドを関連付けています:

<Button Content="計算実行" FontSize="16">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <i:InvokeCommandAction Command="{Binding MouseEnterCommand}"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <i:InvokeCommandAction Command="{Binding MouseLeaveCommand}"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseDoubleClick">
            <i:InvokeCommandAction Command="{Binding CalculateCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

この手法により、クリックだけでなく、マウスの移動やダブルクリックなどの 다양한イベントに対して、コマンドベースの処理を追加できます。

4. MVVM採用の効果

MVVMパターンを適用することで、 단위テストの容易化、保守性の向上、コードの再利用性といった恩恵が得られます。ViewModelはUIフレームワークに依存しない形でロジックを実装できるため、ビューの変更影響をViewModelに波及させずに済みます。

タグ: MVVM WPF C# データバインディング コマンドパターン

6月21日 16:25 投稿