我有一个CSLA
对象,其中包含两个托管属性和一个自定义Attribute
。
要求是至少有一个属性为null。
换句话说: 如果属性A设置为某个且属性B已具有值,则属性A和B将变为无效。在消隐属性B时,属性A应该有效,反之亦然。
为了解决这个问题,我在属性设置器中调用Validator.ValidateProperty
以在设置B时验证属性A,反之亦然。
问题是错误提供程序没有更新。当属性A具有值并且属性得到更新时,错误提供者出现在两个框周围,这非常好。当消隐属性A时,错误提供程序离开txtBoxA并保持在txtBoxB周围,即使我在设置属性A后触发了属性B的验证。请注意第二个我尝试修改属性B错误提供程序消失。我看起来就像我没有正确调用验证的方式。
这个问题让我疯了。我不确定我做错了什么。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
class CustomAttribute : ValidationAttribute
{
private readonly string _other;
public CustomAttribute(string other)
{
_other = other;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var property = validationContext.ObjectType.GetProperty(_other);
if (property == null)
{
return new ValidationResult(
string.Format("Unknown property: {0}", _other)
);
}
var otherValue = property.GetValue(validationContext.ObjectInstance, null);
if (!String.IsNullOrEmpty(value.ToString()) && !String.IsNullOrEmpty(otherValue.ToString()))
{
return new ValidationResult("At least on property has to be null !");
}
return null;
}
}
public class Example : BusinessBase<Example>
{
public static PropertyInfo<string> AProperty = RegisterProperty<String>(p => p.A);
[CustomAttribute("B")]
public string A
{
get { return GetProperty(AProperty); }
set { SetProperty(AProperty, value);
if (B != "")
{
try
{
Validator.ValidateProperty(B, new ValidationContext(this) { MemberName = "B" });
}
catch (Exception)
{
}
}
}
}
public static readonly PropertyInfo<string> BProperty = RegisterProperty<String>(p => p.B);
[CustomAttribute("A")]
public string B
{
get { return GetProperty(BProperty); }
set { SetProperty(BProperty, value);
if (A != "")
{
try
{
Validator.ValidateProperty(A, new ValidationContext(this) { MemberName = "A" });
}
catch (Exception)
{
}
}
}
}
}
<TextBox Name="txtBoxA" Width="300" Text="{Binding A, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
<TextBox Name="txtBoxB" Width="300" Text="{Binding B, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
答案 0 :(得分:1)
我通过创建自定义CSLA
BusinessRule
解决了该问题。使两个属性相互依赖。
using Csla;
using Csla.Rules;
using System;
using System.ComponentModel.DataAnnotations;
protected override void AddBusinessRules()
{
BusinessRules.AddRule(new CustomBusinessRule(AProperty));
BusinessRules.AddRule(new CustomBusinessRule(BProperty));
BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(AProperty, BProperty));
BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(BProperty, AProperty));
}
using System;
using System.Collections.Generic;
using Csla.Rules;
public class CustomBusinessRule : BusinessRule
{
public OnlyOneOutPutLocationBusinessRule(Csla.Core.IPropertyInfo primaryProperty) : base(primaryProperty)
{
InputProperties = new List<Csla.Core.IPropertyInfo> { primaryProperty };
}
protected override void Execute(RuleContext context)
{
Example target = (Example)context.Target;
if (!string.IsNullOrEmpty(ReadProperty(target, Example.A).ToString()) && !String.IsNullOrEmpty(ReadProperty(target, Example.B).ToString()))
{
context.AddErrorResult("At least on property has to be null !");
}
}
}