XAML:
<TextBox Name="textboxMin"> <TextBox.Text> <Binding Path="Max"> <Binding.ValidationRules> <local:IntValidator/> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox>
代码:
void buttonOK_Click(object sender, RoutedEventArgs e) { // I need to know here whether textboxMin validation is OK // textboxMin. ??? // I need to write something like: // if ( textboxMin.Validation.HasErrors ) // return; }
如果至少有一个对话框控件没有通过验证,那么如何知道如何禁用OK按钮会更好 - 在XAML中,使用绑定。有了这种方式,我不需要在代码中检查验证状态。
答案 0 :(得分:24)
Validation.HasError是一个附加属性,因此你可以像这样检查textboxMin
void buttonOK_Click(object sender, RoutedEventArgs e)
{
if (Validation.GetHasError(textboxMin) == true)
return;
}
要在代码中运行TextProperty的所有ValidationRules,您可以获取BindingExpression并调用UpdateSource
BindingExpression be = textboxMin.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
更新
如果发生任何验证,将需要一些步骤来实现绑定以禁用按钮。
首先,确保所有绑定都添加NotifyOnValidationError =“True”。实施例
<TextBox Name="textboxMin">
<TextBox.Text>
<Binding Path="Max" NotifyOnValidationError="True">
<Binding.ValidationRules>
<local:IntValidator/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
然后我们将一个EventHandler挂钩到Window中的Validation.Error事件。
<Window ...
Validation.Error="Window_Error">
在代码背后,我们在observablecollection中添加和删除验证错误,因为它们来来去去
public ObservableCollection<ValidationError> ValidationErrors { get; private set; }
private void Window_Error(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
ValidationErrors.Add(e.Error);
}
else
{
ValidationErrors.Remove(e.Error);
}
}
然后我们可以将Button的IsEnabled绑定到ValidationErrors.Count,就像这样
<Button ...>
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ValidationErrors.Count}" Value="0">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
答案 1 :(得分:6)
在获得规则之前,你需要先获得Binding
Binding b= BindingOperations.GetBinding(textboxMin,TextBox.TextProperty);
b.ValidationRules
否则你可以使用BindingExpression并检查HasError属性
BindingExpression be1 = BindingOperations.GetBindingExpression (textboxMin,TextBox.TextProperty);
be1.HasError
答案 2 :(得分:0)
非常感谢Fredrik Hedblad的解决方案。它也帮助了我。我同意LukášKoten的说法,它最适合用作行为。这样,视图层中不会混合使用混合的应用程序逻辑,并且视图模型不必担心复制验证只是为了简单地将其放在那里。这是我的行为版本:
正如Fredrik Hedblad所说,首先要确保任何控件验证都具有绑定属性NotifyOnValidationError =“True”。
这是视图逻辑......更简单......
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
然后在Window开始标记
下面 Height="Auto" Width="Auto">
<i:Interaction.Behaviors>
<behavior:ValidationErrorMappingBehavior HasValidationError="{Binding IsInvalid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</i:Interaction.Behaviors
然后对于按钮,只需像正常一样绑定命令。我们将使用基本的视图模型绑定原则来使用RelayCommand禁用它。
<Button x:Name="OKButton" Content="OK" Padding="5,0" MinWidth="70" Height="23"
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="5,5,0,0"
Command="{Binding OKCommand}"/>
现在视图模型及其基本属性和命令
private bool _isInvalid = false;
public bool IsInvalid
{
get { return _isInvalid; }
set { SetProperty<bool>(value, ref _isInvalid); }
}
private ICommand _okCommand;
public ICommand OKCommand
{
get
{
if (_okCommand == null)
{
_okCommand = new RelayCommand(param => OnOK(), canparam => CanOK());
}
return _okCommand;
}
}
private void OnOK()
{
// this.IsInvalid = false, so we're good... let's just close
OnCloseRequested();
}
private bool CanOK()
{
return !this.IsInvalid;
}
现在,行为
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace UI.Behavior
{
public class ValidationErrorMappingBehavior : Behavior<Window>
{
#region Properties
public static readonly DependencyProperty ValidationErrorsProperty = DependencyProperty.Register("ValidationErrors", typeof(ObservableCollection<ValidationError>), typeof(ValidationErrorMappingBehavior), new PropertyMetadata(new ObservableCollection<ValidationError>()));
public ObservableCollection<ValidationError> ValidationErrors
{
get { return (ObservableCollection<ValidationError>)this.GetValue(ValidationErrorsProperty); }
set { this.SetValue(ValidationErrorsProperty, value); }
}
public static readonly DependencyProperty HasValidationErrorProperty = DependencyProperty.Register("HasValidationError", typeof(bool), typeof(ValidationErrorMappingBehavior), new PropertyMetadata(false));
public bool HasValidationError
{
get { return (bool)this.GetValue(HasValidationErrorProperty); }
set { this.SetValue(HasValidationErrorProperty, value); }
}
#endregion
#region Constructors
public ValidationErrorMappingBehavior()
: base()
{ }
#endregion
#region Events & Event Methods
private void Validation_Error(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
this.ValidationErrors.Add(e.Error);
}
else
{
this.ValidationErrors.Remove(e.Error);
}
this.HasValidationError = this.ValidationErrors.Count > 0;
}
#endregion
#region Support Methods
protected override void OnAttached()
{
base.OnAttached();
Validation.AddErrorHandler(this.AssociatedObject, Validation_Error);
}
protected override void OnDetaching()
{
base.OnDetaching();
Validation.RemoveErrorHandler(this.AssociatedObject, Validation_Error);
}
#endregion
}
}