「東雲 忠太郎」の平凡な日常のできごと

「東雲 忠太郎」の平凡な日常のできごと

2024.08.03
XML
カテゴリ: WPFC#.NET


C#のWPFアプリケーションにおいて、MVVMパターンを使用してValidation(検証)を実装する方法とその解説を以下に示します。この例では、`INotifyDataErrorInfo`インターフェースを使用してプロパティの検証を行います。


### 1. プロジェクトの準備




### 2. ViewModelの作成


まず、`INotifyDataErrorInfo`インターフェースを実装したViewModelを作成します。このViewModelには、検証ロジックが含まれます。


```csharp

using System;

using System.Collections;

using System.Collections.Generic;

using System.ComponentModel;

using System.Globalization;

using System.Runtime.CompilerServices;


namespace WpfApp.ViewModels

{

    public class MainViewModel : INotifyPropertyChanged, INotifyDataErrorInfo

    {

        private string _dateOfBirth;

        private readonly Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();


        public string DateOfBirth

        {

            get => _dateOfBirth;

            set

            {

                _dateOfBirth = value;

                OnPropertyChanged();

                ValidateDateOfBirth();

            }

        }


        public event PropertyChangedEventHandler PropertyChanged;


        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)

        {

            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        }


        private void ValidateDateOfBirth()

        {

            ClearErrors(nameof(DateOfBirth));

            if (string.IsNullOrWhiteSpace(DateOfBirth))

            {

                AddError(nameof(DateOfBirth), "Date of birth cannot be empty.");

            }

            else if (!DateTime.TryParseExact(DateOfBirth, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedDate))

            {

                AddError(nameof(DateOfBirth), "Date of birth must be in the format yyyy-MM-dd.");

            }

            else if (parsedDate < new DateTime(1900, 1, 1) || parsedDate > DateTime.Today)

            {

                AddError(nameof(DateOfBirth), "Date of birth must be between 01/01/1900 and today.");

            }

        }


        #region INotifyDataErrorInfo


        public bool HasErrors => _errors.Count > 0;


        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;


        public IEnumerable GetErrors(string propertyName)

        {

            return _errors.ContainsKey(propertyName) ? _errors[propertyName] : null;

        }


        private void AddError(string propertyName, string error)

        {

            if (!_errors.ContainsKey(propertyName))

            {

                _errors[propertyName] = new List<string>();

            }

            if (!_errors[propertyName].Contains(error))

            {

                _errors[propertyName].Add(error);

                OnErrorsChanged(propertyName);

            }

        }


        private void ClearErrors(string propertyName)

        {

            if (_errors.ContainsKey(propertyName))

            {

                _errors.Remove(propertyName);

                OnErrorsChanged(propertyName);

            }

        }


        private void OnErrorsChanged(string propertyName)

        {

            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));

        }


        #endregion

    }

}

```


### 3. Viewの作成


次に、XAMLファイルでViewを作成し、テキストボックスにバインディングと検証エラーの表示を設定します。


```xml

<Window x:Class="WpfApp.Views.MainWindow"

        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:vm="clr-namespace:WpfApp.ViewModels"

        mc:Ignorable="d"

        Title="MainWindow" Height="200" Width="400">

    <Window.DataContext>

        <vm:MainViewModel />

    </Window.DataContext>

    <Grid>

        <TextBox x:Name="dateOfBirthTextBox"

                 Text="{Binding DateOfBirth, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"

                 HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" VerticalAlignment="Top" Width="360"/>

        <TextBlock Text="{Binding (Validation.Errors).CurrentItem.ErrorContent, ElementName=dateOfBirthTextBox}"

                   Foreground="Red" HorizontalAlignment="Left" Margin="10,40,0,0" VerticalAlignment="Top"/>

    </Grid>

</Window>

```


### 4. エラースタイルの設定(オプション)


エラーが発生した場合に、エラーのスタイルを設定することもできます。これにより、ユーザーに視覚的なフィードバックを提供します。


```xml

<Window.Resources>

    <Style TargetType="TextBox">

        <Style.Triggers>

            <Trigger Property="Validation.HasError" Value="True">

                <Setter Property="ToolTip" Value="{Binding (Validation.Errors).CurrentItem.ErrorContent, RelativeSource={RelativeSource Self}}" />

                <Setter Property="BorderBrush" Value="Red" />

            </Trigger>

        </Style.Triggers>

    </Style>

</Window.Resources>

```


### 完成したプロジェクト構造


```

WpfApp

├── App.xaml

├── App.xaml.cs

├── ViewModels

│   └── MainViewModel.cs

├── Views

│   └── MainWindow.xaml

│   └── MainWindow.xaml.cs

```


### 解説


1. **ViewModelの作成**:

   - `INotifyPropertyChanged`と`INotifyDataErrorInfo`を実装します。

   - `DateOfBirth`プロパティに対して、入力値の検証を行います。

   - `ValidateDateOfBirth`メソッドを使用して、入力された日付が空でないか、正しい形式か、指定された範囲内であるかを確認します。

   - 検証エラーを保持し、エラーが変更されたことを通知します。


2. **Viewの作成**:

   - `TextBox`に対して、`DateOfBirth`プロパティをバインディングします。

   - `ValidatesOnDataErrors=True`を設定して、データエラーの検証を有効にします。

   - `TextBlock`を使用して、検証エラーを表示します。


3. **エラースタイルの設定**(オプション):

   - スタイルとトリガーを使用して、エラーが発生した場合に`TextBox`の境界線を赤色に変更し、ツールチップにエラーメッセージを表示します。


### まとめ


C#のWPFアプリケーションでMVVMパターンを使用してValidationを実装することで、ビューとビジネスロジックを明確に分離し、コードの再利用性、メンテナンス性、ユーザーエクスペリエンスを向上させることができます。この例では、`INotifyDataErrorInfo`インターフェースを使用して、リアルタイムで検証エラーを通知し、エラーメッセージをユーザーに提供しています。






お気に入りの記事を「いいね!」で応援しよう

Last updated  2024.08.03 18:15:50


【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! -- / --
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x
X

© Rakuten Group, Inc.
X
Design a Mobile Website
スマートフォン版を閲覧 | PC版を閲覧
Share by: