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

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

2024.08.03
XML
カテゴリ: WPFC#.NET


C#のWPFでMVVMパターンを使用して日付の入力規則を設定する方法を紹介します。ここでは、日付の入力が正しい形式かどうか、特定の範囲内にあるかどうかをチェックする例を示します。


### 手順




Visual Studioで新しいWPFアプリケーションプロジェクトを作成します。


#### 2. ViewModelの作成


日付の入力規則を含むViewModelを作成します。`INotifyDataErrorInfo`インターフェースを実装して、プロパティのエラーチェックを行います。


```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 DateTime? _dateOfBirth;

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


        public DateTime? 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 (!DateOfBirth.HasValue)

            {

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

            }

            else if (DateOfBirth < new DateTime(1900, 1, 1) || DateOfBirth > 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 Text="{Binding DateOfBirth, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, StringFormat=d}" 

                 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

```


### 実行結果




### 実行結果


アプリケーションを実行すると、`TextBox`に日付を入力できるようになります。日付が空である場合、または1900年1月1日より前、または今日より後の日付を入力した場合、エラーメッセージが表示されます。正しい日付が入力されると、エラーメッセージは消えます。


### 追加の機能


#### 1. DatePickerの使用


WPFでは、日付の入力を簡単にするために`DatePicker`コントロールを使用することもできます。`DatePicker`を使用すると、ユーザーはカレンダーから日付を選択できるため、入力ミスが減ります。


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

        <DatePicker SelectedDate="{Binding DateOfBirth, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" 

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

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

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

    </Grid>

</Window>

```


#### 2. カスタムバリデーションルールの作成


`ValidationRule`クラスを継承してカスタムバリデーションルールを作成し、バインディングに適用することもできます。


```csharp

using System;

using System.Globalization;

using System.Windows.Controls;


public class DateValidationRule : ValidationRule

{

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)

    {

        if (value == null || string.IsNullOrWhiteSpace(value.ToString()))

        {

            return new ValidationResult(false, "Date of birth cannot be empty.");

        }


        if (DateTime.TryParse(value.ToString(), out DateTime date))

        {

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

            {

                return new ValidationResult(false, "Date of birth must be between 01/01/1900 and today.");

            }

            return ValidationResult.ValidResult;

        }


        return new ValidationResult(false, "Invalid date format.");

    }

}

```


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

        xmlns:local="clr-namespace:WpfApp"

        mc:Ignorable="d"

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

    <Window.DataContext>

        <vm:MainViewModel />

    </Window.DataContext>

    <Grid>

        <TextBox x:Name="dateOfBirthTextBox" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" VerticalAlignment="Top" Width="360">

            <TextBox.Text>

                <Binding Path="DateOfBirth" UpdateSourceTrigger="PropertyChanged">

                    <Binding.ValidationRules>

                        <local:DateValidationRule />

                    </Binding.ValidationRules>

                </Binding>

            </TextBox.Text>

        </TextBox>

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

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

    </Grid>

</Window>

```


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


```

WpfApp

├── App.xaml

├── App.xaml.cs

├── ViewModels

│   └── MainViewModel.cs

├── Views

│   └── MainWindow.xaml

│   └── MainWindow.xaml.cs

├── ValidationRules

│   └── DateValidationRule.cs

```


### まとめ


このサンプルでは、WPFでMVVMパターンを使用して日付の入力規則を設定する方法を示しました。`INotifyDataErrorInfo`インターフェースを使用してプロパティの検証を行い、`DatePicker`コントロールやカスタムバリデーションルールを使用することで、ユーザーが正しい形式の日付を入力するよう支援します。このアプローチを使用することで、他の入力フィールドに対しても同様に検証ロジックを追加できます。






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

Last updated  2024.08.03 13:01:35


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

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