FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

データ検証用の属性を作成する

 今回はSystem.ComponentModel.DataAnnotationsを利用したデータ検証で、オリジナルのデータ検証用属性を作成し使用してみたいと思います。
 サンプルコードでは、文字列の最低長をチェックする属性を作ります。
 まずは、検証用属性を作成します
using System;
using System.ComponentModel.DataAnnotations;

namespace Validation5.CustomValidationAttribute
{
    /// <summary>
    /// 最低文字数を検証する属性
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
    public class MinimumStringLengthAttribute : ValidationAttribute
    {

        public MinimumStringLengthAttribute(int minimumLength)
            :base()
        {
            MinimumLength = minimumLength;
        }

        /// <summary>
        /// 文字列の最低長を設定、又は取得する。
        /// </summary>
        public int MinimumLength { get; set; }

        /// <summary>
        /// 検証を行う。
        /// </summary>
        /// <param name="value">値</param>
        /// <returns>検証結果</returns>
        public override bool IsValid(object value)
        {
            if (value == null) return false;

            return value.ToString().Length >= MinimumLength;
        }
    }
}
 オリジナルのデータ検証用属性を作成する場合はValidationAttributeを継承する必要があります。
 属性クラスはお約束として最後にAttributeとつける必要があります。
 AttributeUsage属性でこの属性の性質を指定します。
[AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
 この属性はプロパティ用の属性なのでAttributeTargetsはPropertyを指定しています。また、最低長の指定を行うのは1プロパティにつき1回だけなのでAllowMultipleをfalseにしています。
 値の検証を行うIsValid(object value)メソッドをオーバーライドし、値のチェック結果を返します。
 これで、オリジナルの検証用属性が完成しました。
 この属性の使用方法は、他のデータ検証用属性の使い方と全く同じです。
 では、この属性を使ってデータ検証を行ってみます。
using Livet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
using Validation5.CustomValidationAttribute;

namespace Validation5.ViewModels
{
    public class MainWindowViewModel : ViewModel, INotifyDataErrorInfo
    {
        private Dictionary<string, string[]> Errors = new Dictionary<string, string[]>();


        #region Value変更通知プロパティ
        private string _Value;
        [MinimumStringLength(5, ErrorMessage="5文字以上入力してください。")]
        public string Value
        {
            get
            { return _Value; }
            set
            { 
                if (_Value == value)
                    return;
                _Value = value;
                RaisePropertyChanged();
                UpdateErrors(value);
            }
        }
        #endregion


        // エラー情報が変更された際に発生するイベント
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        // ErrorsChangedイベントを発生させる
        protected virtual void RaiseErrorsChanged([CallerMemberName]string propertyName = "")
        {
            var h = this.ErrorsChanged;
            if (h != null)
            {
                h(this, new DataErrorsChangedEventArgs(propertyName));
            }
        }

        // エラーメッセージを取得する
        public System.Collections.IEnumerable GetErrors(string propertyName)
        {
            if (string.IsNullOrWhiteSpace(propertyName)) return null;
            if (!Errors.ContainsKey(propertyName)) return null;
            return Errors[propertyName];
        }

        // エラーの有無
        public bool HasErrors
        {
            get { return Errors.Values.Any(x => x != null); }
        }

        // エラー情報を更新する。
        private void UpdateErrors(object value, [CallerMemberName]string propertyName = "")
        {
            if (string.IsNullOrWhiteSpace(propertyName)) return;

            var results = new List<ValidationResult>();

            if (Validator.TryValidateProperty(
                value,
                new ValidationContext(this, null, null) { MemberName = propertyName },
                results))
            {
                // エラー無し
                Errors[propertyName] = null;
            }
            else
            {
                Errors[propertyName] = results.Select(x => x.ErrorMessage).ToArray();
            }

            RaiseErrorsChanged(propertyName);
        }
    }
}
 ViewModelでは、先ほど作成したオリジナルの検証用属性を使用しています。
 データ検証の方法は、前回紹介した方法と同じなので説明は省略します。
<Window x:Class="Validation5.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:Validation5.Views"
        xmlns:vm="clr-namespace:Validation5.ViewModels"
        Title="MainWindow" Height="350" Width="525">
    
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>

    <Window.Resources>
        <ControlTemplate x:Key="ErrorTemplate">
            <DockPanel>
                <ItemsControl DockPanel.Dock="Right"
                              ItemsSource="{Binding ElementName=adornedElement, Path=AdornedElement.(Validation.Errors)}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

                <Border BorderBrush="Red" BorderThickness="1"
                        Width="{Binding ElementName=adornedElement, Path=ActualWidth}"
                        Height="{Binding ElementName=adornedElement, Path=ActualHeight}">
                    <AdornedElementPlaceholder Name="adornedElement"/>
                </Border>
            </DockPanel>
        </ControlTemplate>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        
        <TextBlock Grid.Column="0" Text="文字列:"/>
        <TextBox Grid.Column="1"
                 Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
                 Validation.ErrorTemplate="{StaticResource ErrorTemplate}"/>
    </Grid>
</Window>
 これを実行し、エラーが出るように値を入力すると以下の様になります。
データ検証5
 こんな感じで簡単にオリジナルの検証用属性が作成できます。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

カレンダー
10 | 2018/11 | 12
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
全記事表示リンク

全ての記事を表示する

カテゴリ
タグリスト

月別アーカイブ
11  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09 
最新記事
リンク
最新コメント
検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。