首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Caliburn.Micro实现INotifyDataErrorInfo

Caliburn.Micro实现INotifyDataErrorInfo
EN

Stack Overflow用户
提问于 2014-05-21 08:01:24
回答 2查看 922关注 0票数 2

我试图找到一个优雅的解决方案,用INotifiyDataErrorInfo MVVM框架来实现Caliburn.Micro。

我希望限制每个需要实现验证的VM中重复的代码数量。我首先编写了一个继承Screen并实现INotifiyDataErrorInfo的类。它正确地工作,一切都很好,直到我需要验证一个VM,它不是一个Screen,而是一个Conductor

当然,我可以创建一个继承Conductor并实现INotifyDataErrorInfo的类,但这是非常烦人的,因为我基本上必须创建自己的所有Caliburn.Micro“基类”。

一个解决方案是保留Screen基类并创建一个IValidator接口,然后将其插入到VM中,如下所示:

代码语言:javascript
复制
public interface IValidator<T> where T : INotifyDataErrorInfo
{
    void Validates(T instance);

    IEnumerable GetErrors(string propertyName);
    bool HasErrors { get; }

    void Validate();
    void ValidateProperty<TValue>(TValue value, string propertyName = null);
    void ValidateProperty<TValue, TProperty>(TValue value, Expression<Func<TProperty>> property);
}

然后,它将以这种方式在VM中使用。

代码语言:javascript
复制
public class CreateCarViewModel : Conductor<CreateCarViewModel>.Collection.OneActive, INotifyDataErrorInfo
{
   private readonly IValidator<CreateCarViewModel> validator;

   public CreateExperimentViewModel(IValidator<CreateCarViewModel> validator)
   {
       this.DisplayName = "Select a car";

       this.validator = validator;
       this.validator.Validates(this);
   }

   [Required]
   public string CarName
   {
       get
       {
           return this.carName;
       }
       set
       {
           if (this.carName != value)
           {
               this.carName = value;

               this.validator.ValidateProperty(value, () => this.CarName);
               this.NotifyOfPropertyChange(() => CarName);
           }
       }
   }

   public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

   public System.Collections.IEnumerable GetErrors(string propertyName)
   {
       return this.validator.GetErrors(propertyName);
   }

   public bool HasErrors
   {
       get { return this.validator.HasErrors; }
   }

   ...

}

这非常好,因为在VM中实现INotifyDataErrorInfo非常简单,但我遇到的问题是触发ErrorChanged事件。它必须由IValidator的实现触发,因为他知道错误何时发生了变化,当然也不能直接触发。

我的一个想法是在IValidator中拥有一个事件,并在VM中订阅它,这样它就可以触发它自己的事件,但是我发现它使很多代码变得毫无意义。

有人有更好的主意吗?

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-21 16:52:39

如果您让IValidator公开与VM相同的事件,那么连线代码不会过多,例如:

代码语言:javascript
复制
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public void Validate()
    {
        if (ErrorsChanged != null)
            ErrorsChanged(instance, new DataErrorsChangedEventArgs("someProperty"));
    }

在VM中:

代码语言:javascript
复制
 validator.ErrorsChanged += (sender, args) => ErrorsChanged(sender, args);

但我想你已经没有告诉我们就回答了你自己的问题;)

票数 0
EN

Stack Overflow用户

发布于 2015-01-28 21:18:54

我为CM编写了一个小插件,以支持流畅的构建器风格的验证。也许它能帮到你。您可以随意使用它:https://github.com/AIexandr/Caliburn.Micro.Validation用法示例:

代码语言:javascript
复制
public class PaymentEditorViewModel() : ValidatingScreen
{
  public PaymentEditorViewModel()
  {
    AddValidationRule(() => PaymentSum).Condition(() => PaymentSum <= 0).Message("Please enter payment sum");
  }

  #region PaymentSum property
  decimal _PaymentSum;
  public decimal PaymentSum
  {
    get
    {
      return _PaymentSum;
    }
    set
    {
      _PaymentSum = value;
      NotifyOfPropertyChange(() => PaymentSum);
    }
  }
  #endregion
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23777395

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档