Download - 60分でわかる!SilverlightとWPFの入力チェック
60分でわかる!SilverlightとWPFの 入力チェック
グレープシティ株式会社
八巻 雄哉
VSUG DAY 2010 Winter
VSUG DAY 2010.12.11
“入力チェック”とは
2
UIが受け取ったユーザー入力の妥当性を検証し、結果に応じて何らかの アクションをとること
ユーザー入力後、コントロールに保持されている入力値を検証し、結果に応じてユーザーへの通知を行うというアクションをとる
VSUG DAY 2010.12.11
検証
TextBoxに入力された 値が数値かどうかを 確認する
アクション
メッセージをToolTipで表示する
3
検証とアクション
VSUG DAY 2010.12.11
検証 60分でわかる!SilverlightとWPFの入力チェック
4
VSUG DAY 2010.12.11
WPF/Silverlightの検証
WPF/Silverlightでは、 データバインディングのプロセスの1つ として検証機能が提供されている
バインディング オブジェクト
UI要素 データ
オブジェクト
依存関係 プロパティ
プロパティ 検証 変換
バインディングソース バインディングターゲット
5
VSUG DAY 2010.12.11
本セッションのデモを図解
6
バインディング オブジェクト
TextBox Customer オブジェクト
Text プロパティ
AccountNameプロパティ
検証 abc@
abc@
abc@
バインディングソース バインディングターゲット
VSUG DAY 2010.12.11
検証処理実装方法の種類
7
ValidatesOn***プロパティをTrueに設定した場合、***ValidationRuleを 設定したときと同じ動作となる。 Silverlight 4/Windows Phone OS 7.0にはValidationRulesプロパティが存在しないため、 必ずValidatesOn***を使用する。
WPF 4 Silverlight 4 Windows Phone OS
7.0
① ValidationRuleを継承した カスタムクラス
✔ - -
② Exception(例外)によるエラー通知 ExceptionValidationRule ValidatesOnExceptions
✔ ✔
- ✔
- ✔
③ IDataErrorInfoによるエラー通知 DataErrorValidationRule ValidatesOnDataErrors
✔ ✔
- ✔
- -
④ INotifyDataErrorInfoによるエラー通知 ValidatesOnNotifyDataErrors
-
✔
-
VSUG DAY 2010.12.11
ValidationRulesプロパティ使用
8
<TextBox> <TextBox.Text> <Binding Path="AccountName"> <Binding.ValidationRules> <ExceptionValidationRule/> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox>
WPF 4
VSUG DAY 2010.12.11
ValidatesOn***プロパティ使用
9
<TextBox Text="{Binding AccountName, ValidatesOnExceptions=True}"/>
Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
2つの検証処理実装場所
10
バインディングソース バインディングターゲット
UI要素 データオブジェクト
依存関係 プロパティ
プロパティ
①ValidationRule
②Exception
④INotifyDataErrorInfo
③IDataErrorInfo
VSUG DAY 2010.12.11
①ValidationRule
11
WPF 4
VSUG DAY 2010.12.11
①ValidationRule
12
<Binding Path="AccountName"> <Binding.ValidationRules> <local:AccountNameValidationRule/> </Binding.ValidationRules> </Binding>
Customer
AccountName プロパティ
WPF 4
TextBox
Text プロパティ
バインディング オブジェクト
カスタムValidationRule
ValidationResultを返す
VSUG DAY 2010.12.11
カスタムValidationRule
13
class AccountNameValidationRule : ValidationRule { public override ValidationResult Validate(object value, System.Glob・・・
{ if (string.IsNullOrEmpty((string)value)) { return new ValidationResult(false, "必須入力項目です。"); } else if (!Regex.IsMatch((string)value, "^[0-9A-Za-z]{5,12}$")) { return new ValidationResult(false, "半角英数字5 文字以上12文字以下で入力
してください。"); } return ValidationResult.ValidResult; }
} WPF 4
VSUG DAY 2010.12.11
DEMO ①ValidationRule
14
VSUG DAY 2010.12.11
②Exception
15
Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
②Exception
16
<TextBox Text="{Binding AccountName, ValidatesOnExceptions=True}"/>
Silverlight 4 WPF 4 Windows Phone OS 7.0
Customer
AccountName プロパティ
TextBox
Text プロパティ
バインディング オブジェクト
検証処理
ValidatesOnExceptions=True
例外をスロー
VSUG DAY 2010.12.11
Exception(例外)によるエラー通知
17
public string AccountName { get { return _accountName; } set { if (string.IsNullOrEmpty((string)value)) { throw new Exception("必須入力項目です。");
} else if (!Regex.IsMatch((string)value, "^[0-9A-Za-z]{5,12}$")) { throw new Exception("半角英数字5文字以上12文字以下で入力してください。");
} _accountName = value; } } Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
DEMO ②Exception
18
VSUG DAY 2010.12.11
System.ComponentModel. DataAnnotations名前空間
19
Silverlight 4 WPF 4
VSUG DAY 2010.12.11
ValidationException(検証例外)
20
デバッグ実行で中断しない設定 (Visual Studio 2010既定)
VSUG DAY 2010.12.11
検証属性を利用した検証処理
21
カスタムの検証属性
DataType列挙体に用意された データ型(電話番号など)を指定
特定の列挙体を指定し、値が含まれることを保証
最小値および最大値の制約を指定
正規表現を使用して有効な値を指定
値が必須であることを指定
最大文字数および最小文字数を指定
ValidationAtt
ribute(検証属性)
CustomValidationAttribute
DataTypeAttribute
EnumDataTypeAttribute
RangeAttribute
RegularExpressionAttribute
RequiredAttribute
StringLengthAttribute
VSUG DAY 2010.12.11
Validatorクラス
22
検証属性を使用するためのヘルパークラス
ValidatePropertyメソッド
指定されたプロパティの値が有効であるかどうかを判断し、プロパティが有効でない場合は、ValidationExceptionをスローします。
VSUG DAY 2010.12.11
検証属性を使用して例外をスロー
23
[Required(ErrorMessage = "必須入力項目です。")] [RegularExpression(@"^[0-9A-Za-z]{5,12}$", ErrorMessage = "半角英数字5文字以上12文字以下で入力してください。")] public string AccountName { get { return _accountName; } set { Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "AccountName" }); _accountName = value; } }
Silverlight 4 WPF 4
VSUG DAY 2010.12.11
DEMO ②Exception + 検証属性
24
VSUG DAY 2010.12.11
③IDataErrorInfo
25
Silverlight 4 WPF 4
VSUG DAY 2010.12.11
③IDataErrorInfo
26
<TextBox Text="{Binding AccountName, ValidatesOnDataErrors=True}"/>
Silverlight 4 WPF 4
Customer
AccountName プロパティ
TextBox
Text プロパティ
バインディング オブジェクト
Itemプロパティ
ValidatesOnDataErrors=True
検証エラーメッセージ(String)を返す
VSUG DAY 2010.12.11
IDataErrorInfoのメンバー
27
Errorプロパティ
オブジェクトの検証エラーを説明する文字列を取得。エラーが存在しない場合はnull参照。
Itemプロパティ(インデクサ)
指定されたプロパティの検証エラーを説明する文字列を取得。エラーが存在しない場合はnull参照。
VSUG DAY 2010.12.11
サンプルコード( IDataErrorInfo )
28
public string this[string columnName] { get { switch (columnName) { case "AccountName": if (string.IsNullOrEmpty(AccountName)) { return "必須入力項目です。"; } else if (!Regex.IsMatch(AccountName, "^[0-9A-Za-z]{5,12}$")) { return "半角英数字5文字以上12文字以下で入力してください。"; } break; } return null; } }
Silverlight 4 WPF 4
VSUG DAY 2010.12.11
DEMO ③IDataErrorInfo
29
VSUG DAY 2010.12.11
Validatorクラス (System.ComponentModel.DataAnnotations名前空間)
30
検証属性を使用するためのヘルパークラス
ValidatePropertyメソッド
指定されたプロパティの値が有効であるかどうかを判断し、値が有効でない場合はValidationExceptionをスローします。
TryValidatePropertyメソッド
指定されたプロパティ値が有効であるかどうかを判断し、値が有効な場合はTrue、そうでない場合はFalseを返します。
VSUG DAY 2010.12.11
検証属性を使用して判定
31
public string this[string columnName] { get { 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; } }
Silverlight 4 WPF 4
VSUG DAY 2010.12.11
DEMO ③IDataErrorInfo + 検証属性
32
VSUG DAY 2010.12.11
④INotifyDataErrorInfo
33
Silverlight 4
VSUG DAY 2010.12.11
④INotifyDataErrorInfo
34
<TextBox Text="{Binding AccountName, ValidatesOnNotifyDataErrors=True}"/>
Silverlight 4
既定でTrue
Customer
AccountName プロパティ
TextBox
Text プロパティ
バインディング オブジェクト
GetErrors メソッド
ValidatesOnNotifyDataErrors=True
検証エラー情報の コレクションを返す
ErrorsChangedイベント
VSUG DAY 2010.12.11
INotifyDataErrorInfoのメンバー
35
GetErrorsメソッド
指定されたプロパティの検証、およびオブジェクトの検証におけるエラー情報(複数可)を取得。エラーが存在しない場合はnull参照。
HasErrorsプロパティ
オブジェクトの検証エラーの有無をBoolean値として取得
ErrorsChangedイベント
プロパティまたはオブジェクト全体の検証エラーが変更されたときに発生
VSUG DAY 2010.12.11
DataErrorInfoの優位点
36
1つの項目で複数の検証エラーを返せる
エラー内容として文字列(String)以外の情報を設定可能(①も可)
データバインディングによる値の更新 に同期せず、任意のタイミングで検証 可能
VSUG DAY 2010.12.11
INotifyDataErrorInfoの実装例
37
public System.Collections.IEnumerable GetErrors(string propertyName) { var results = new List<ValidationResult>(); if (Validator.TryValidateProperty( GetType().GetProperty(propertyName).GetValue(this, null), new ValidationContext(this, null, null) { MemberName = propertyName }, results)) { return null; } return results; }
Silverlight 4
VSUG DAY 2010.12.11
ErrorsChangedイベントの発行
38
public string AccountName { get { return _accountName; } set { // 実際にはここで非同期処理でサーバー側で値を検証し // ErrorsChangedイベントを発行する
RaiseErrorsChanged("AccountName");
_accountName = value; } }
Silverlight 4
VSUG DAY 2010.12.11
DEMO ④INotifyDataErrorInfo + 検証属性
39
VSUG DAY 2010.12.11
アクション 60分でわかる!SilverlightとWPFの入力チェック
40
VSUG DAY 2010.12.11
検証エラー発生時に何が起こるのか?
41
その検証エラーに対応したValidationError オブジェクトが作成され、バインドされている 要素のValidation.Errors添付プロパティ
(読み取り専用のコレクション)に追加される
ValidationErrorクラス
ErrorContentプロパティ
エラーメッセージを取得
Exceptionプロパティ
検証エラーの原因となった例外を取得
VSUG DAY 2010.12.11
本セッションのデモを図解
42
バインディング オブジェクト
TextBox Customer オブジェクト
Text プロパティ
AccountNameプロパティ
検証 abc@ abc@
バインディングソース バインディングターゲット
Validation.Errors添付プロパティ
ValidationErrorオブジェクト “5文字以上12文字以下です。”
ValidationErrorオブジェクト “半角英数字のみ使用できます。”
VSUG DAY 2010.12.11
検証アクション実装方法の種類
43
Validation.Errors添付プロパティの値に応じて、各種検証アクションのための仕組みが動作する
WPF Silverlight Windows Phone OS 7.0
a. ErrorTemplate ✔ - -
b. ValidationStates (VSM)
✔ 既定ではVisualStateは定義
されていない
✔ ✔ 既定で定義されている
VisualStateは空
c. HasError 添付プロパティ (プロパティトリガー)
✔ ✔
✔ -
✔ -
d. イベント ✔
Validation.Error 添付イベント
✔ FrameworkElement.BindingValidationErrorイベント
✔ FrameworkElement.BindingValidationErrorイベント
VSUG DAY 2010.12.11
a. ErrorTemplate添付プロパティ
44
WPF 4
VSUG DAY 2010.12.11
a. ErrorTemplate添付プロパティ
45
Validation.Errors添付プロパティの値が空でない(検証条件に対して無効な値が設定されている)場合に、ErrorTemplate添付プロパティに設定されたテンプレート(外観)が表示される
VSUG DAY 2010.12.11
a. ErrorTemplate添付プロパティ
46
Validation.ErrorTemplate(ControlTemplate型)
AdornedElementPlaceholderはErrorTemplateが適用される要素(今回の場合TextBox)を表す
<Validation.ErrorTemplate> <ControlTemplate> <Border BorderBrush="#FFFF0000" BorderThickness="1,1,1,1"> <AdornedElementPlaceholder /> </Border> </ControlTemplate> </Validation.ErrorTemplate>
デフォルトのErrorTemplate
WPF 4
VSUG DAY 2010.12.11
DEMO a. ErrorTemplate添付プロパティ
47
VSUG DAY 2010.12.11
b. VisualStateManager(VSM)
48
Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
b. VisualStateManager(VSM)
49
動的な外観状態と、その外観状態に遷移する 条件や遷移にかかる時間を管理する一連の機能 を提供するのがVSM
ValidationStates(VisualStateGroup)
Errors添付 プロパティ
VisualState 説明
空 Valid コントロールが有効
空でない
InvalidFocused フォーカスがある状態で、コントロールが無効
InvalidUnfocused フォーカスがない状態で、コントロールが無効
“見た目”を決めるコントロール・テンプレート - @IT
http://www.atmarkit.co.jp/fdotnet/vblab/uiframework_04/uiframework_04_03.html
VSUG DAY 2010.12.11
VSMの優位点
50
値が無効な場合だけでなく、値が有効な場合の外観も定義できる
外観への遷移方法(VisualTransition)を定義できる
難点
Expression Blendがないとちょっとキツイ
VSUG DAY 2010.12.11
DEMO b. VisualStateManager(VSM)
51
VSUG DAY 2010.12.11
c. HasError添付プロパティ
52
Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
c. HasError添付プロパティ(プロパティトリガー)
53
Validation.HasError
ValidationErrorが存在する場合はTrue
<Style TargetType="TextBox"> <Style.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> <Setter Property="Background" Value="Red"/> </Trigger> </Style.Triggers> </Style>
WPF 4
VSUG DAY 2010.12.11
Silverlightのドキュメントより抜粋
54
WPFでは、プロパティトリガーによってデータ検証が実行される場合があります。その場合、Validation.HasErrorは、TriggerのProperty属性値をチェックするためのプロパティ条件として使用されます。
このようなイベントハンドラーは、コード中のオブジェクトのValidation.HasError添付プロパティをチェックすることができますが、通常はGetHasErrorメソッドを呼び出すか、またはHasErrorProperty識別子を使用して GetValue メソッドを呼び出します。
BindingValidationErrorイベントのハンドラーは、通常、検証を行うためにそのロジックの一部として特定のVisualStateに変更されます。
VSUG DAY 2010.12.11
d. イベント
55
Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
d. イベント
56
WPF 4 Validation.Error添付イベント
Silverlight 4/Windows Phone OS 7.0 FrameworkElement.BindingValidationErrorイベント
ValidationErrorが追加/削除された際に 発生するイベント
Binding.NotifyOnValidationErrorプロパティをTrueに設定する必要あり
これらのイベントはルーティングイベント (バブル)となっているため、親要素の イベントハンドラーで通知を受け取ることが可能
VSUG DAY 2010.12.11
d. イベント
57
イベントの引数ValidationErrorEventArgsに 含まれているActionプロパティ
ValidationErrorEventAction.Added 新しいValidationErrorオブジェクトが検出された
ValidationErrorEventAction.Removed 既存のValidationErrorが削除された
if (e.Action == ValidationErrorEventAction.Added) { // 検証エラーが発生した時の処理
} else if (e.Action == ValidationErrorEventAction.Removed) { //検証エラーがなくなった時の処理
}
Silverlight 4 WPF 4 Windows Phone OS 7.0
VSUG DAY 2010.12.11
DEMO d. イベント
58
VSUG DAY 2010.12.11
まとめ
59
検証
① ValidationRule
② Exception
③ IDataErrorInfo
④ INotifyDataErrorInfo
アクション
a. ErrorTemplate添付プロパティ
b. VisualStateManager(VSM)
c. HasError添付プロパティ(プロパティトリガー)
d. イベント
VSUG DAY 2010.12.11
検証のまとめ図
60
① ValidationRule
② Exception
③ IDataErrorInfo
④ INotifyDataErrorInfo
検証処理実装 場所
バインディングターゲット
バインディングソース
バインディングソース
バインディングソース
検証属性の利用 - ✔ ✔ ✔
文字列以外の 検証エラー内容
✔ - - ✔
複数の検証 エラー通知
- - - ✔
任意のタイミングで検証
- - - ✔
利用可能プラットフォーム
WPF 4 WPF 4 Silverlight 4 Windows Phone
WPF 4 Silverlight 4
Silverlight 4
VSUG DAY 2010.12.11
アクションのまとめ図
61
a. ErrorTemplate添付プロパティ
b. VisualStateManager(VSM)
c. HasError添付プロパティ(プロパティトリガー)
d. イベント
サポートされる検証結果
無効
有効 無効(フォーカス有)
無効(フォーカス無)
有効 無効
有効 無効 ※フォーカス対応化
アクションの記述
XAML XAML XAML (コードの場合GetHasErrorメソッド)
コード
遷移アニメーションサポート
- ✔ ✔
対象コントロールと無関係の要素の外観を変更
- - ✔ ✔
利用可能プラットフォーム
WPF 4 WPF 4 Silverlight 4 Windows Phone
WPF 4 Silverlight 4 Windows Phone
WPF 4 Silverlight 4 Windows Phone
VSUG DAY 2010.12.11
“入力チェック”とは
62
UIが受け取ったユーザー入力の妥当性を検証し、結果に応じて何らかの アクションをとること
ユーザー入力後、コントロールに保持されている入力値を検証し、結果に応じてユーザーへの通知を行うというアクションをとる
ユーザー入力時に入力を検証し、結果に応じてその入力を無効にする/有効な入力に変換するというアクションをとる
VSUG DAY 2010.12.11
検証タイミングで異なる開発面の特徴
63
入力後
プロパティ値を確認するという 単純処理であるため、難易度が低い
様々なケースに対応できる反面、 汎用化が難しい
入力中
キー入力に加え、マウス操作、貼り付け、 カレット制御などを考慮する必要がある
プリミティブな部分での実装が必要となり 難易度が高い
VSUG DAY 2010.12.11
InputManファミリー
日本の業務アプリケーションに求められる 高度な入力支援機能を提供するコントロール集
for Silverlight for WPF
for Windows Forms
for ASP.NET
64
VSUG DAY 2010.12.11
InputMan for Silverlight 1.0J
65
和暦の表示/入力(M・T・S・Hや元年表示にも対応)
文字種指定の入力制御(ひらがな、カタカナ、記号、全角、半角、スペース、サロゲートペア文字など)
ノンコーディングでフォーカス制御
フリガナ自動取得
祝日の登録や曜日のスタイルを設定できるカレンダー
GcTextBox テキストコントロール GcMask マスクコントロール GcDateTime 日付コントロール GcNumber 数値コントロール GcDropDownCalculator ドロップダウン電卓コントロール GcDropDownCalendar ドロップダウンカレンダーコントロール GcValidationIndicator 検証インジケータコントロール
GcImeManager ふりがな取得コンポーネント
Silverlight標準に不足している業務コントロールをカバー
VSUG DAY 2010.12.11
<im:GcTextBox Format="Aa9" />
Silverlight 4 WPF 4
GcTextBox.Formatプロパティ
66
全角 半角 説明
A A 大文字のアルファベット(A~Z)
a a 小文字のアルファベット(a~z)
K K カタカナ(促音・拗音の小書き表記あり)
N N カタカナ(促音・拗音の小書き表記なし)
9 9 数字(0~9)
# # 数字および数字関連記号(0~9、+ - $ % ¥ , .)
@ @ 記号(! " # $ % & ' ( ) - = ^ ~ ¥ | @ ` [ { ; + : * ] } , < . > / ? _)
B B 2進数(0または1)
X X 16進数(0~9、A~F)
J - ひらがな(促音・拗音の小書き表記あり)
G - ひらがな(促音・拗音の小書き表記なし)
Z - すべての全角文字
T - サロゲート ペア文字
S S 空白文字
- H すべての半角文字
- ^ 指定した書式に含まれないすべての文字
- ¥ エスケープシーケンス
67
VSUG DAY 2010.12.11
Appendix
68
VSUG DAY 2010.12.11
検証属性の自動適用
69
Silverlight 4
VSUG DAY 2010.12.11
検証属性の自動適用
70
Silverlight 4のDataGrid
データ注釈を使用したデータ クラスのカスタマイズ http://msdn.microsoft.com/ja-jp/library/dd901590.aspx
WCF RIA Services
How to: Validate Data http://msdn.microsoft.com/en-us/library/ee707335.aspx
VSUG DAY 2010.12.11
検証ルールの実行タイミング
71
WPF 4
VSUG DAY 2010.12.11
ValidationRule.ValidationStepプロパティ
72
ValidationStep 列挙値
説明 ExceptionValidationRule
DataErrorValidationRule
ValidationRuleを継承したカスタムク
ラス
RawProposedValue
変換が行われる前
デフォルト 不可 デフォルト
ConvertedProposedValue
変換が行われた後 可 不可 可
UpdatedValue
ソースの更新後
可 可 可※
CommittedValue
値がソースにコミットされた後
可 デフォルト 可※
※Validationメソッドの引数valueはBindingExpressionオブジェクト
WPF 4
VSUG DAY 2010.12.11
BindingGroup
73
WPF 4
VSUG DAY 2010.12.11
BindingGroupプロパティ
74
以下の条件のどちらかを満たしている場合、Bindingがグループ化される
BindingのソースとBindingGroupを設定した要素のDataContextが同じ
BindingのBindingGroupNameプロパティが BindingGroupのNameと同じ
<Grid.BindingGroup> <BindingGroup> <BindingGroup.ValidationRules> <local:ObjectValidation/> </BindingGroup.ValidationRules> </BindingGroup> </Grid.BindingGroup>
WPF 4
VSUG DAY 2010.12.11
個々の検証をまとめて実行
75
Bindingがグループ化されることにより、 各Bindingは個別に更新されなくなる。
任意のタイミングで 一気にすべての項目を更新させることが可能
個々の検証をまとめて実行できる。
個々ValidationRuleは、ValidationStepがRawProposedValueであるもののみがBindingGroupの
ValidationRuleよりも前に実行される。
VSUG DAY 2010.12.11
編集トランザクション
76
メソッド名 説明
BeginEdit 編集トランザクションを開始します。
CommitEdit すべてのValidationRuleを実行し、 成功した場合はバインディングソースを更新します。
CancelEdit 編集トランザクションを終了し、保留中の変更を破棄します。
VSUG DAY 2010.12.11
編集トランザクション
77
Private Sub SubmitButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) If LayoutRoot.BindingGroup.CommitEdit() Then MessageBox.Show("登録されました。")
LayoutRoot.BindingGroup.BeginEdit() End If End Sub Private Sub CancelButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) LayoutRoot.BindingGroup.CancelEdit() LayoutRoot.BindingGroup.BeginEdit() End Sub
WPF 4