INotifyDataErrorInfoの実装は、前の記事でやりました。
http://d.hatena.ne.jp/okazuki/20100418/1271594953
ただ、INotifyDataErrorInfoはSilverlight4にしかないので、WPF4だとIDataErrorInfoとかプロパティでの例外で入力値の検証をしないといけません。
とりあえずIDataErrorInfoを汎用的?に実装するとしたらというのをでっちあげてみました。Errorプロパティがちょっと悩みどころですが・・・
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; namespace WpfApplication1 { public class ViewModelBase : INotifyPropertyChanged, IDataErrorInfo { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { var h = PropertyChanged; if (h == null) return; h(this, new PropertyChangedEventArgs(propertyName)); } public string Error { get { // ここ何て実装していいのか悩みどころ、とりあえず全エラー連結してみた var results = new List<ValidationResult>(); if (Validator.TryValidateObject( this, new ValidationContext(this, null, null), results)) { return string.Empty; } return string.Join(Environment.NewLine, results.Select(r => r.ErrorMessage)); } } public string this[string columnName] { get { // TryValidatePropertyで、プロパティを検証 var results = new List<ValidationResult>(); if (Validator.TryValidateProperty( GetType().GetProperty(columnName).GetValue(this, null), new ValidationContext(this, null, null) { MemberName = columnName }, results)) { return null; } // エラーがあれあ最初のエラーを返す return results.First().ErrorMessage; } } } }
こんな感じで使います
using System.ComponentModel.DataAnnotations; namespace WpfApplication1 { public class PersonViewModel : ViewModelBase { private string _fullName; [Required(ErrorMessage = "名前を入力してね")] public string FullName { get { return _fullName; } set { _fullName = value; OnPropertyChanged("FullName"); } } } }
後はWindowにバインドしえ適当にエラーを表示するように細工すると
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:WpfApplication1" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <l:PersonViewModel /> </Window.DataContext> <Grid> <TextBox Height="24" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=FullName, ValidatesOnDataErrors=True}" ToolTip="{Binding ElementName=textBox1, Path=(Validation.Errors)[0].ErrorContent}"/> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="12,42,0,0" Name="button1" VerticalAlignment="Top" Width="75" /> <TextBlock Height="23" HorizontalAlignment="Left" Margin="138,13,0,0" Name="textBlock1" Text="{Binding ElementName=textBox1, Path=(Validation.Errors)[0].ErrorContent}" VerticalAlignment="Top" /> </Grid> </Window>