トップ回答者
1つBinding時に複数のコントロールに、ValidatesOnExceptionsを通知させたい。

質問
-
いつも御世話になっております。
Binding 時のValidationを利用して、TextBoxAとTextBoxBの、どちらかに値が入力されていないとエラーとし、双方の枠を赤くするといった処理を記述したいと考えています。また、逆にどちらかが入力されたら、枠の色を元に戻したいと考えています。
下記のように記述してみたのですが、
throw new ArgumentException() が、呼び出し元のコントロールに通知されるので、
当然のことながら、呼び出し元でValidation Errorがあったと判定されるのみとなります。
xaml<TextBox Text="{Binding Name1, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}"/> <TextBox Text="{Binding Name2, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}"/>
C#
private string name1; public string Name1 { get { return name1; } set { name = value; check(); OnPropertyChanged("Name1"); } } private string name2; public string Name2 { get { return name2; } set { name = value; check(); OnPropertyChanged("Name2"); } } private void check() { if(string.IsNullOrEmpty(name1) && string.IsNullOrEmpty(name2) ) { throw new ArgumentException(); } }
検討がつかず、質問をさせて頂きました。
ご迷惑をおかけしますが、アドバイスいただけないでしょうか?
宜しくお願い致します。
回答
-
ValidatesOnExceptions は1フィールド用です。
ValidatesOnDataErrorsを使ってください。
<Window x:Class="Wpf2Binding.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <TextBox Grid.Row="0" Text="{Binding Name1, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True }"/> <TextBox Grid.Row="1" Text="{Binding Name2, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True}"/> <Button Grid.Row="2" Name="button1" Click="button1_Click">Button</Button> </Grid> </Window>
/// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : Window, INotifyPropertyChanged, IDataErrorInfo { private Dictionary<string, string> _errors = new Dictionary<string, string>(); public Window1() { InitializeComponent(); this.DataContext = this; } private string name1; public string Name1 { get { return name1; } set { if (value != null && value.Length > 10) { _errors["Name1"] = "Too big"; } else { _errors["Name1"] = null; } name1 = value; OnPropertyChanged("Name1"); OnPropertyChanged("Name2"); } } private string name2; public string Name2 { get { return name2; } set { name2 = value; OnPropertyChanged("Name1"); OnPropertyChanged("Name2"); } } #region INotifyPropertyChanged メンバ public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string p) { if (this.PropertyChanged != null) { this.PropertyChanged(this,new PropertyChangedEventArgs(p)); } } #endregion #region IDataErrorInfo メンバ public string Error { get { if (string.IsNullOrEmpty(name1) && string.IsNullOrEmpty(name2)) { return "Empty!"; } return null; } } public bool HasErrors { get { return (_errors.Count != 0 || Error != null); } } public string this[string columnName] { get { if (_errors.ContainsKey(columnName)) { return _errors[columnName]; } if (columnName == "Name1" || columnName == "Name2") { if (string.IsNullOrEmpty(name1) && string.IsNullOrEmpty(name2)) { return "Empty!"; } } return null; } } #endregion private void button1_Click(object sender, RoutedEventArgs e) { if (this.HasErrors) return; // 正常時 } }
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12- 回答としてマーク a_山田 2009年9月11日 2:34
すべての返信
-
ValidatesOnExceptions は1フィールド用です。
ValidatesOnDataErrorsを使ってください。
<Window x:Class="Wpf2Binding.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <TextBox Grid.Row="0" Text="{Binding Name1, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True }"/> <TextBox Grid.Row="1" Text="{Binding Name2, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True}"/> <Button Grid.Row="2" Name="button1" Click="button1_Click">Button</Button> </Grid> </Window>
/// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : Window, INotifyPropertyChanged, IDataErrorInfo { private Dictionary<string, string> _errors = new Dictionary<string, string>(); public Window1() { InitializeComponent(); this.DataContext = this; } private string name1; public string Name1 { get { return name1; } set { if (value != null && value.Length > 10) { _errors["Name1"] = "Too big"; } else { _errors["Name1"] = null; } name1 = value; OnPropertyChanged("Name1"); OnPropertyChanged("Name2"); } } private string name2; public string Name2 { get { return name2; } set { name2 = value; OnPropertyChanged("Name1"); OnPropertyChanged("Name2"); } } #region INotifyPropertyChanged メンバ public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string p) { if (this.PropertyChanged != null) { this.PropertyChanged(this,new PropertyChangedEventArgs(p)); } } #endregion #region IDataErrorInfo メンバ public string Error { get { if (string.IsNullOrEmpty(name1) && string.IsNullOrEmpty(name2)) { return "Empty!"; } return null; } } public bool HasErrors { get { return (_errors.Count != 0 || Error != null); } } public string this[string columnName] { get { if (_errors.ContainsKey(columnName)) { return _errors[columnName]; } if (columnName == "Name1" || columnName == "Name2") { if (string.IsNullOrEmpty(name1) && string.IsNullOrEmpty(name2)) { return "Empty!"; } } return null; } } #endregion private void button1_Click(object sender, RoutedEventArgs e) { if (this.HasErrors) return; // 正常時 } }
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12- 回答としてマーク a_山田 2009年9月11日 2:34
-
現象は確認しました。
仕様的なものかはわからないです。
ここでバグとしてレポートしてほしいです。
https://connect.microsoft.com/VisualStudioJapan
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12 -
-
あれ、質問を書き直されたのですね。
赤い枠が残ることは確認しました。
仕様的なもので正常な動作かはわからないです。
ここでバグとしてレポートしてほしいです。(日本語でOKです)
ここでの答えで仕様的なもので正常な動作かどうかがわかります。
https://connect.microsoft.com/VisualStudioJapan
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12