1

我有一个CSLA具有两个托管属性和一个自定义的对象Attribute。要求是至少有一个属性为空。

换句话说:如果属性 A 被设置为某些东西并且属性 B 已经有一个值,那么属性 A 和 B 将变为无效。消隐属性 B 后,属性 A 应变为有效,反之亦然。

为了解决这个问题,我Validator.ValidateProperty在属性设置器中调用了在设置 B 时验证属性 A,反之亦然。

问题是错误提供程序没有更新。当属性 A 有一个值并且属性得到更新时,错误提供程序会出现在两个框周围,这很好。当清空属性 A 时,即使我在设置属性 A 后触发了属性 B 的验证,错误提供程序也会离开 txtBoxA 并停留在 txtBoxB 附近。请注意我尝试修改属性 B 的第二次错误提供程序消失了。我看起来像我没有正确调用验证的方式。

这个问题快把我逼疯了。我不确定我做错了什么。

C#

[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)
                        {


                        }

                    }

                }
            }
        }

wpf#

<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}" />
4

1 回答 1

1

我通过创建自定义解决了这个问题CSLA BusinessRule。An 使这两个属性相互依赖。

将此方法添加到业务对象类示例#

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 !");

                }
            }
        }
于 2016-08-10T18:59:40.073 回答