[保存]ボタンをクリックする前に、いくつかのテキストボックスを空にできないページがあります。
<TextBox...
<TextBox.Text>
<Binding Path ="LastName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:StringRequiredValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
私のルールは機能します。値を入力するまで、テキストボックスの周りに赤い枠があります。そこで、この検証ルールを他のテキストボックスに追加します。
では、ページにエラーがなくなるまで[保存]ボタンを無効にするにはどうすればよいですか。検証エラーがあるかどうかを確認するために何をチェックすべきかわかりません。
ビューの分離コードでは、Validation.ErrorEventを次のように結び付けることができます。
this.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(OnErrorEvent));
その後
private int errorCount;
private void OnErrorEvent(object sender, RoutedEventArgs e)
{
var validationEventArgs = e as ValidationErrorEventArgs;
if (validationEventArgs == null)
throw new Exception("Unexpected event args");
switch(validationEventArgs.Action)
{
case ValidationErrorEventAction.Added:
{
errorCount++; break;
}
case ValidationErrorEventAction.Removed:
{
errorCount--; break;
}
default:
{
throw new Exception("Unknown action");
}
}
Save.IsEnabled = errorCount == 0;
}
これは、削除の通知を受け取ることを前提としています(無効な要素を削除した場合は発生しません)。
Validation.HasError 添付プロパティを使用したい。
同じように、ジョシュ・スミスは Binding to(Validation.Errors)[0] without Createing Debug Spew について興味深い記事を読んでいます。
int count = 0;
private void LayoutRoot_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
button1.IsEnabled = false;
count++;
}
if (e.Action == ValidationErrorEventAction.Removed)
{
count--;
if (count == 0) button1.IsEnabled = true;
}
}
以下は、依存関係オブジェクト(およびそのすべての子)の検証エラーを追跡し、デリゲートを呼び出して変更について通知するヘルパーメソッドです。また、検証エラーのある子の削除も追跡します。
public static void AddErrorHandler(DependencyObject element, Action<bool> setHasValidationErrors)
{
var errors = new List<Tuple<object, ValidationError>>();
RoutedEventHandler sourceUnloaded = null;
sourceUnloaded = (sender, args) =>
{
if (sender is FrameworkElement)
((FrameworkElement) sender).Unloaded -= sourceUnloaded;
else
((FrameworkContentElement) sender).Unloaded -= sourceUnloaded;
foreach (var error in errors.Where(err => err.Item1 == sender).ToArray())
errors.Remove(error);
setHasValidationErrors(errors.Any());
};
EventHandler<ValidationErrorEventArgs> errorHandler = (_, args) =>
{
if (args.Action == ValidationErrorEventAction.Added)
{
errors.Add(new Tuple<object, ValidationError>(args.OriginalSource, args.Error));
if (args.OriginalSource is FrameworkElement)
((FrameworkElement)args.OriginalSource).Unloaded += sourceUnloaded;
else if (args.OriginalSource is FrameworkContentElement)
((FrameworkContentElement)args.OriginalSource).Unloaded += sourceUnloaded;
}
else
{
var error = errors
.FirstOrDefault(err => err.Item1 == args.OriginalSource && err.Item2 == args.Error);
if (error != null)
errors.Remove(error);
}
setHasValidationErrors(errors.Any());
};
System.Windows.Controls.Validation.AddErrorHandler(element, errorHandler);
}
これは、背後のコードからHasErrorコントロールプロパティを確認する必要があることです
保存ボタンをクリックしてこのコードを実行します
BindingExpression bexp = this.TextBox1.GetBindingExpression(TextBox.TextProperty);
bexp.UpdateSource(); // this to refresh the binding and see if any error exist
bool hasError = bexp.HasError; // this is boolean property indique if there is error
MessageBox.Show(hasError.ToString());
上記の解決策のいくつかを試しました。しかし、どれも私のために働いていませんでした。
ユーザーにURIを要求する単純な入力ウィンドウがあります。TextBox
値が有効なUri
でない場合、Okay
ボタンを無効にする必要があります。
これが私のために働いたものです:
CommandBindings.Add(new CommandBinding(AppCommands.Okay,
(sender, args) => DialogResult = true,
(sender, args) => args.CanExecute = !(bool) _uriTextBoxControl.GetValue(Validation.HasErrorProperty)));
validateのSystem.ComponentModel.IDataErrorInfoから、および通知ボタンのINotifyPropertyChangedからViewModelを継承するだけです
プロパティを作成:
public bool IsValid
{
get
{
if (this.FloorPlanName.IsEmpty())
return false;
return true;
}
}
xAMLでボタンに接続します
<Button Margin="4,0,0,0" Style="{StaticResource McVMStdButton_Ok}" Click="btnDialogOk_Click" IsEnabled="{Binding IsValid}"/>
iDataErrorInfoオーバーライドで、btuttonに通知
public string this[string columnName]{
get
{
switch (columnName)
{
case "FloorPlanName":
if (this.FloorPlanName.IsEmpty())
{
OnPropertyChanged("IsValid");
return "Floor plan name cant be empty";
}
break;
}
}
}
まだ足りないので、リンクが消えてしまった場合に備えて、開発者の回答を以下に示します。
XAML:
<TextBox.Text Validation.Error="handleValidationError">
<Binding Path ="LastName"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<local:StringRequiredValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<Button IsEnabled="{Binding HasNoValidationErrors}"/>
CodeBehind/C#:
private int _numberOfValidationErrors;
public bool HasNoValidationErrors => _numberOfValidationErrors = 0;
private void handleValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
_numberOfValidationErrors++;
else
_numberOfValidationErrors--;
}