验证规则属性:如何在不使用依赖项属性的情况下绑定



在我的WPF MVVM应用程序中,我有一个绑定了验证规则的TextBox。在验证规则类中,我有以下属性:

public bool CanBeValidated { get; set; } = false;

然后在视图中,我的TextBox有以下验证规则绑定(我只放了相关部分(:

<TextBox.Text>
<Binding Path="myPath"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<vRules:RootPathValidationRule 
ValidatesOnTargetUpdated="True" 
CanBeValidated="{Binding Path=ValidationEnabled}"/>
</Binding.ValidationRules>
</Binding>                         
</TextBox.Text> 

在我的视图模型中,属性定义如下:

public bool ValidationEnabled
{ 
get { return _isValidationEnabled; }
set { this._isValidationEnabled = value; OnPropertyChanged(); }
}

所以我收到以下编译错误:

不能对类型的"CanBeValidated"属性设置"Binding"MyPathValidatorRule"。只能在DependencyObject的DependencyProperty。

第一次加载TextBox时,我希望避免在用户编辑之前触发验证规则,并避免由于TextBox为空而引发验证错误。

一旦用户编辑了TextBox,我想通过执行一个简单的this来启用验证规则。ValidationEnabled=视图模型中的true。

如何在不使用依赖属性的情况下实现这一点?有可能吗?

您可以创建一个从DependencyObject派生并公开依赖属性的包装器类。然后将CLR属性添加到ValidationRule类中,该类返回以下包装类型的实例:

public class RootPathValidationRule : ValidationRule
{
public Wrapper Wrapper { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
bool canBeValidated = Wrapper?.CanBeValidated == true;
...
}
}
public class Wrapper : DependencyObject
{
public static readonly DependencyProperty CanBeValidatedProperty =
DependencyProperty.Register(nameof(CanBeValidated), typeof(bool),
typeof(Wrapper));
public bool CanBeValidated
{
get { return (bool)GetValue(CanBeValidatedProperty); }
set { SetValue(CanBeValidatedProperty, value); }
}
}

最后,您还需要一个绑定代理对象来捕获DataContext,其中定义了源属性:

public class BindingProxy : System.Windows.Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
}

XAML:

<TextBox>
<TextBox.Resources>
<vRules:BindingProxy x:Key="proxy" Data="{Binding}"/>
</TextBox.Resources>
<TextBox.Text>
<Binding Path="myPath"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<vRules:RootPathValidationRule ValidatesOnTargetUpdated="True">
<vRules:RootPathValidationRule.Wrapper>
<vRules:Wrapper CanBeValidated="{Binding Data.ValidationEnabled, 
Source={StaticResource proxy}}"/>
</vRules:RootPathValidationRule.Wrapper>
</vRules:RootPathValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>

有关详细信息,请参阅本文。

最新更新