WPF_Prism_ErrorsContainer
ErrorsContainerについて
ErrorsContainerとは
ErrorsContainerは、INotifyDataErrorInfoの実装ヘルパークラスです。
INotifyDataErrorInfo実装時に、発生中のエラー情報を保持するためにDictionary型のメンバを用意してましたが、管理が煩雑だという問題がありました。
そこで、発生中のエラー情報を簡単に扱えるようにするためのクラスがErrorsContainerです。
実装について
ErrorsContainerでは、下記処理を各ViewModelにそれぞれ追加することになります。
- ErrorsContainerのフィールド作成する。
- ErrorsContainerを使ってINotifyDataErrorInfoの実装する。
- 入力値検証用のメソッド作成する。
- プロパティに入力値検証のための実装を行う。
ErrorsContainer実装例
System.ComponentModel.DataAnnotationsの参照が必要です。
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
namespace WpfPrismMvvm
{
public class MainWindowViewModel : BindableBase, INotifyDataErrorInfo
{
private string _firstname;
[Required(ErrorMessage = "名前の入力は必須です。")]
public string FirstName
{
get { return this._firstname; }
set
{
this.SetProperty(ref this._firstname, value);
this.ValidateProperty(value);
}
}
private string _lastname;
[Required(ErrorMessage = "性の入力は必須です。")]
public string LastName
{
get { return this._lastname; }
set
{
this.SetProperty(ref this._lastname, value);
this.ValidateProperty(value);
}
}
public MainWindowViewModel()
{
_errorsContainer = new ErrorsContainer<string>(OnErrorsChanged);
this.FirstName = string.Empty;
this.LastName = string.Empty;
}
/// <summary>
/// 入力値の検証を行う。
/// </summary>
/// <memo>System.ComponentModel.DataAnnotationsの参照を追加すること</memo>
/// <param name="value">入力値</param>
/// <param name="propertyName">プロパティ名</param>
protected void ValidateProperty(object value, [CallerMemberName]string propertyName = null)
{
var context = new ValidationContext(this) { MemberName = propertyName };
var validationErrors = new List<ValidationResult>();
if (!Validator.TryValidateProperty(value, context, validationErrors))
{
var errors = validationErrors.Select(error => error.ErrorMessage);
this._errorsContainer.SetErrors(propertyName, errors);
}
else
{
this._errorsContainer.ClearErrors(propertyName);
}
}
#region INotifyDataErrorInfoの実装
/// <summary>
/// 保持したいエラー情報の型を指定して、ErrorsContainerのフィールドを作成する。
/// </summary>
private ErrorsContainer<string> _errorsContainer;
/// <summary>
/// エラーに変更があったときに通知される。
/// </summary>
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
/// <summary>
/// 指定したプロパティのエラー情報を取得する。
/// </summary>
/// <param name="propertyName">プロパティ名</param>
/// <returns>エラー情報</returns>
public System.Collections.IEnumerable GetErrors(string propertyName)
{
return _errorsContainer.GetErrors(propertyName);
}
/// <summary>
/// 指定したプロパティ名のエラーに変更があったことを通知する。
/// <param name="propertyName">プロパティ名</param>
/// </summary>
private void OnErrorsChanged([CallerMemberName] string propertyName = null)
{
var handler = this.ErrorsChanged;
if (handler != null)
{
handler(this, new DataErrorsChangedEventArgs(propertyName));
}
}
/// <summary>
/// エラーがある場合trueを返す。
/// </summary>
public bool HasErrors
{
get
{
return _errorsContainer.HasErrors;
}
}
#endregion
}
}
xaml
Validation.ErrorTemplateを設定します。
<Window x:Class="WpfPrismMvvm.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"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="300">
<Window.Resources>
<ControlTemplate x:Key="ValidationTemplate">
<StackPanel>
<TextBlock Foreground="Red" Text="{Binding AdornedElement.(Validation.Errors)[0].ErrorContent, ElementName=adornedelem}" />
<AdornedElementPlaceholder x:Name="adornedelem" />
</StackPanel>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="FirstName: " Margin="5,20,5,5" />
<TextBox Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}"
MinWidth="200" Height="20" Margin="5,20,5,5" HorizontalAlignment="Left" TextWrapping="Wrap"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="LastName: " Margin="5,20,5,5" />
<TextBox Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}"
MinWidth="200" Height="20" Margin="5,20,5,5" HorizontalAlignment="Left" TextWrapping="Wrap"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />
</StackPanel>
</StackPanel>
</Window>
関連ページ
- WPF_Prism_BindableBase
- WPF_Prism_DelegateCommand
- WPF_Prism_InteractionRequest
- WPF_Prism_CompositeCommand
- WPF_Prism_ErrorsContainer
- WPF_Prism_InvokeCommandAction
- C#