簡體   English   中英

Caliburn.Micro實現INotifyDataErrorInfo

[英]Caliburn.Micro implementing INotifyDataErrorInfo

我正在嘗試找到一種優雅的解決方案,以利用Caliburn.Micro MVVM框架實現INotifiyDataErrorInfo

我想限制在每個需要實施驗證的VM中重復的代碼量。 我從編寫一個繼承Screen並實現INotifiyDataErrorInfo的類開始。 它可以正常工作,並且一切都很好,直到我需要在不是Screen而是Conductor的VM上進行驗證為止。

當然,我可以制作一個繼承Conductor並實現INotifyDataErrorInfo的類,但是這很煩人,因為我必須基本上自己INotifyDataErrorInfo Caliburn.Micro所有“基本”類的版本。

我的一個解決方案是保留Screen基類,並創建一個IValidator接口,將其注入到我的VM中,如下所示:

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中使用。

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; }
   }

   ...

}

這非常INotifyDataErrorInfo ,因為在VM中實現INotifyDataErrorInfo非常簡單,但是我遇到的問題是觸發ErrorChanged事件。 它必須由IValidator的實現來觸發,因為他是知道錯誤何時已更改的人,當然他不能直接觸發。

我的一個想法是在IValidator有一個事件,然后在VM中訂閱它,以便它可以觸發自己的事件,但是我發現它無濟於事地編寫了很多代碼。

有誰有更好的主意嗎?

謝謝

我為CM寫了一個小插件,以啟用流暢的生成器樣式驗證。 也許會對您有幫助。 隨時使用它: https : //github.com/AIexandr/Caliburn.Micro.Validation使用示例:

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
}

如果您讓IValidator公開了與VM相同的事件,則聯結代碼是否過多,例如:

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

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

並在VM中:

 validator.ErrorsChanged += (sender, args) => ErrorsChanged(sender, args);

但是我想你已經回答了自己的問題了,沒有告訴我們;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM