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

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

2024.08.03
XML
カテゴリ: WPFC#.NET


C#のWPFでMVVMパターンを使用し、テキストボックスに日付の入力規則を付ける方法を以下に示します。この例では、`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

    }

}

```


### 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>

```


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


エラーが発生した場合に、エラーのスタイルを設定することもできます。


```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

```


### 実行結果


アプリケーションを実行すると、`TextBox`に日付を入力できるようになります。入力された日付が空である場合、正しい形式でない場合、または指定された範囲内にない場合、エラーメッセージが表示されます。正しい日付が入力されると、エラーメッセージは消えます。


このアプローチを使用することで、他の入力フィールドに対しても同様に検証ロジックを追加できます。






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

Last updated  2024.08.03 13:04:54


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

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