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

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

2024.08.14
XML
カテゴリ: WPFC#.NET


C# WPF でインデクサを利用して入力エラーを管理する方法を解説します。この方法では、`IDataErrorInfo` インターフェースを使用し、プロパティ名をキーとするエラーメッセージの辞書をインデクサを介して管理します。


### **1. Model クラス (`Person`)**




```csharp

using System.ComponentModel;

using System.Collections.Generic;


namespace WpfAppValidationExample

{

    public class Person : IDataErrorInfo, INotifyPropertyChanged

    {

        private string _name;

        private int _age;


        // エラーメッセージを格納するための辞書

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


        public string Name

        {

            get => _name;

            set

            {

                _name = value;

                OnPropertyChanged(nameof(Name));

            }

        }


        public int Age

        {

            get => _age;

            set

            {

                _age = value;

                OnPropertyChanged(nameof(Age));

            }

        }


        public event PropertyChangedEventHandler PropertyChanged;


        protected void OnPropertyChanged(string propertyName)

        {

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

        }


        // IDataErrorInfo インターフェースのプロパティ。全体のエラー状態を返します。

        public string Error => null;


        // インデクサを使ってプロパティごとのエラーを返します。

        public string this[string propertyName]

        {

            get

            {

                string error = null;


                switch (propertyName)

                {

                    case nameof(Name):

                        if (string.IsNullOrWhiteSpace(Name))

                        {

                            error = "Name is required.";

                        }

                        else if (Name.Length < 2)

                        {

                            error = "Name must be at least 2 characters long.";

                        }

                        else if (!IsAlpha(Name))

                        {

                            error = "Name must contain only letters.";

                        }

                        break;


                    case nameof(Age):

                        if (Age <= 0 || Age > 120)

                        {

                            error = "Age must be between 1 and 120.";

                        }

                        break;

                }


                // エラーメッセージを辞書に保存または削除

                if (error != null)

                {

                    _errors[propertyName] = error;

                }

                else

                {

                    _errors.Remove(propertyName);

                }


                return error;

            }

        }


        // 名前に文字のみが含まれているかを確認するヘルパーメソッド

        private bool IsAlpha(string input)

        {

            foreach (char c in input)

            {

                if (!char.IsLetter(c))

                {

                    return false;

                }

            }

            return true;

        }

    }

}

```


### **2. ViewModel クラス (`MainViewModel`)**


`Person` クラスを含むシンプルな ViewModel クラスです。


```csharp

using System.ComponentModel;


namespace WpfAppValidationExample

{

    public class MainViewModel : INotifyPropertyChanged

    {

        private Person _person;


        public MainViewModel()

        {

            _person = new Person();

        }


        public Person Person

        {

            get => _person;

            set

            {

                _person = value;

                OnPropertyChanged(nameof(Person));

            }

        }


        public event PropertyChangedEventHandler PropertyChanged;


        protected void OnPropertyChanged(string propertyName)

        {

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

        }

    }

}

```


### **3. View (XAML)**


WPF の UI 定義は次の通りです。`TextBox` にバインディングされたプロパティのエラーが発生すると、そのエラーが `Validation.ErrorTemplate` によって表示されます。


```xml

<Window x:Class="WpfAppValidationExample.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Input Validation Example" Height="250" Width="400">

    <Window.DataContext>

        <local:MainViewModel />

    </Window.DataContext>

    <Grid Margin="20">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="Auto"/>

        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Margin="0 0 0 10">

            <TextBlock Text="Name:" />

            <TextBox Text="{Binding Person.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

        </StackPanel>

        <StackPanel Grid.Row="1" Margin="0 0 0 10">

            <TextBlock Text="Age:" />

            <TextBox Text="{Binding Person.Age, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

        </StackPanel>

        <Button Content="Submit" Grid.Row="2" Width="100" Height="30" />

    </Grid>

</Window>

```


### **4. MainWindow.xaml.cs**


`MainWindow.xaml.cs` で何もする必要はありませんが、プロジェクトに追加する必要があります。


```csharp

using System.Windows;


namespace WpfAppValidationExample

{

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

    }

}

```


### **動作確認**


このサンプルコードでは、`Name` および `Age` プロパティに対するエラーメッセージを、`IDataErrorInfo` インターフェースのインデクサを通じて管理しています。


- **Name**

  - 空白または `null` の場合: 「Name is required.」

  - 2文字未満の場合: 「Name must be at least 2 characters long.」

  - 文字以外が含まれている場合: 「Name must contain only letters.」


- **Age**

  - 1 未満または 120 を超える場合: 「Age must be between 1 and 120.」


エラーが発生した場合、`TextBox` の下にエラーメッセージが表示されます。


### **まとめ**


この方法では、`IDataErrorInfo` のインデクサを使用してプロパティごとのエラーメッセージを管理します。プロパティ名をキーとする辞書を利用してエラーを追跡し、各プロパティのバリデーションロジックを簡単に実装できます。このパターンは、比較的シンプルなバリデーション要件に対応する場合に適しています。






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

Last updated  2024.08.14 14:51:23


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

© Rakuten Group, Inc.
X
Mobilize your Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: