使用WPFvalidation规则并禁用“保存”button
我有一个页面,点击保存button之前,几个文本框不能为空。
<TextBox... <TextBox.Text> <Binding Path ="LastName" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <local:StringRequiredValidationRule /> </Binding.ValidationRules> </Binding> </TextBox.Text>
我的规则起作用。 我在我的文本框周围有一个红色的边框,直到我input一个值。 所以现在我想将这个validation规则添加到我的其他文本框。
现在,如何禁用保存button,直到页面没有错误? 我不知道要检查是否有任何validation错误。
这里是你需要的完整样本。
http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
https://skydrive.live.com/?cid=2c6600f1c1d5e3be&id=2C6600F1C1D5E3BE%21203
在视图的代码隐藏你可以像这样连接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附加属性。
沿着同样的线路乔希·史密斯有一个有趣的阅读绑定到(Validation.Errors)[0]没有创builddebugging的发言 。
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; } }
这是跟踪依赖对象(及其所有子对象)上的validation错误的辅助方法,并调用委托通知有关更改。 它还跟踪删除有validation错误的儿童。
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控制属性
并在保存button点击做这个代码
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());
我已经尝试了上面提到的几个解决scheme。 但是,他们没有一个为我工作。
我的简单问题
我有一个简单的input窗口,请求来自用户的URI,如果TextBox
值不是有效的Uri
那么Okay
button应该被禁用。
我的简单解决scheme
这是什么对我有用:
CommandBindings.Add(new CommandBinding(AppCommands.Okay, (sender, args) => DialogResult = true, (sender, args) => args.CanExecute = !(bool) _uriTextBoxControl.GetValue(Validation.HasErrorProperty)));
只是从System.ComponentModel.IDataErrorInfo inhert您的ViewModelvalidation和从INotifyPropertyChanged通知button
使财产:
public bool IsValid { get { if (this.FloorPlanName.IsEmpty()) return false; return true; } }
在xaml中,将其连接到button
<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; } } }