2017-08-20 19 views
1

我試圖啓用一個按鈕,當綁定屬性嵌套字段被輸入時有界,但即使所有屬性都填充了數據,該按鈕也被禁用。 我應該改變什麼?在Exrin VisualState中嵌套對象的無效擴展

這是我的基地可視狀態

public class BaseVisualState : Exrin.Framework.VisualState 
{ 
public BaseVisualState() : this(null) 
{ 
} 

public BaseVisualState(IBaseModel i_Model) : base(i_Model) 
{ 
PropertyObservable = Observable.FromEventPattern(
       (EventHandler<PropertyChangedEventArgs> i_Event) => new PropertyChangedEventHandler(i_Event), 
       i_EventChanged => this.PropertyChanged += i_EventChanged, 
       i_EventChanged => this.PropertyChanged -= i_EventChanged); 
     } 

     public IObservable<EventPattern<PropertyChangedEventArgs>> PropertyObservable { get; private set; } 
    } 

和我的視覺狀態是

public class BeaconAddVisualState : BaseVisualState 
    { 
     private readonly IBeaconAddModel r_Model; 

     public BeaconAddVisualState(IBeaconAddModel i_Model) 
      : base(i_Model) 
     { 
      r_Model = i_Model; 
     } 

     [Binding(BindingType.TwoWay)] 
     public Beacon Beacon 
     { 
      get 
      { 
       return Get<Beacon>(); 
      } 

      set 
      { 
       Set(value); 
      } 
     } 

     public override async void Init() 
     { 
      Beacon = new Beacon(); 
     } 
    } 

信標類物業通知改變

public class Beacon : Document<Guid>, INotifyPropertyChanged 
    { 
     private string m_ProximityUuid; 
     private int? m_Major; 
     private int? m_Minor; 

     [Required] 
     public string ProximityUuid 
     { 
      get 
      { 
       return m_ProximityUuid; 
      } 

      set 
      { 
       if(m_ProximityUuid != value) 
       { 
        m_ProximityUuid = value; 
        notifyPropertyChanged(); 
       } 
      } 
     } 

     [Required] 
     public int? Major 
     { 
      get 
      { 
       return m_Major; 
      } 

      set 
      { 
       if (m_Major != value) 
       { 
        m_Major = value; 
        notifyPropertyChanged(); 
       } 
      } 
     } 

     [Required] 
     public int? Minor 
     { 
      get 
      { 
       return m_Minor; 
      } 

      set 
      { 
       if (m_Minor != value) 
       { 
        m_Minor = value; 
        notifyPropertyChanged(); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     // This method is called by the Set accessor of each property. 
     // The CallerMemberName attribute that is applied to the optional propertyName 
     // parameter causes the property name of the caller to be substituted as an argument. 
     private void notifyPropertyChanged([CallerMemberName] string i_PropertyName = "") 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(i_PropertyName)); 
      } 
     } 
    } 

,這是視圖模型

public class BeaconAddViewModel : BaseAuthViewModel 
    { 
     private readonly IBeaconAddModel r_Model; 
     private readonly IDisposable r_Subscription; 

     public BeaconAddViewModel(IBeaconAddModel i_Model) 
      : base(new BeaconAddVisualState(i_Model)) 
     { 
      r_Model = i_Model; 
      r_Subscription = State.PropertyObservable.Where(
       i_Arg => i_Arg.EventArgs.PropertyName == nameof(State.Beacon.ProximityUuid) 
         || i_Arg.EventArgs.PropertyName == nameof(State.Beacon.Major) || i_Arg.EventArgs.PropertyName == nameof(State.Beacon.Minor)).Subscribe(
       i_Arg => 
        { 
         AddCommand.OnCanExecuteChanged(); 
        }); 
     } 

     private BeaconAddVisualState State => VisualState as BeaconAddVisualState; 

     public override Task OnNavigated(object i_Args) 
     { 
      return base.OnNavigated(i_Args); 
     } 

     public IRelayCommand AddCommand 
     { 
      get 
      { 
       return GetCommand(
        () => 
         { 
          return new RelayCommand(
           async (i_Parameter) => 
            { 
             await r_Model.AddBeacon(i_Parameter as Beacon); 
             await NavigationService.Navigate("Beacons"); 
            }, (i_Obj) => !string.IsNullOrEmpty(State.Beacon.ProximityUuid) && State.Beacon.Major.HasValue && State.Beacon.Minor.HasValue; 
         }); 
      } 
     } 

     public override void Disposing() 
     { 
      base.Disposing(); 
      r_Subscription?.Dispose(); 
     } 
    } 

回答

0

這裏的問題是您在Beacon類中觸發INPC,但BaseVisualState僅查看Beacon(對象本身)是否正在改變。

因此,您必須將Beacon以外的屬性直接帶入VisualState或中繼INPC事件。

例如在您所設定的燈塔做

var beacon = value; 
Set(value); 
value.OnPropertyChanged += (s,e) => { OnPropertyChanged(nameof(Beacon)); } 

這將意味着,在每一個信標任何財產發生變化時,它會說,燈塔類本身發生了變化,並觸發INPC爲的VisualState。

注意:確保事件在重置時處於開啓狀態。這意味着不會像上面顯示的那樣在一個匿名函數中執行它,而是執行+ =並將其切換爲另一個方法。

+0

時,它的復位,你的意思是覆蓋的的visualSTATE權處置方法? –

+0

我指的是您將放置在Beacon屬性集中的事件處理程序。確保你解開那個事件。例如value.OnPropertyChanged - = –

+0

是的,你會在VisualState的處置上做到這一點,並且,每次設置該屬性時,都需要這樣做。因此,檢查它是否爲空,如果不是,則刪除現有的事件處理程序。 –

0

感謝Adam的幫助。 這是什麼ID沒有到底,也許它可以幫助別人

public class BeaconAddVisualState : BaseVisualState 
    { 
     private readonly IBeaconAddModel r_Model; 
     private Beacon m_Beacon; 

     public BeaconAddVisualState(IBeaconAddModel i_Model) 
      : base(i_Model) 
     { 
      r_Model = i_Model; 
     } 

     [Binding(BindingType.TwoWay)] 
     public Beacon Beacon 
     { 
      get 
      { 
       return m_Beacon; 
      } 

      set 
      { 
       if(m_Beacon != value) 
       { 
        if(m_Beacon != null) 
        { 
         m_Beacon.PropertyChanged -= m_Beacon_PropertyChanged; 
        } 

        m_Beacon = value; 
        m_Beacon.PropertyChanged += m_Beacon_PropertyChanged; 
        OnPropertyChanged(); 
       } 
      } 
     } 

     public override async void Init() 
     { 
      Beacon = new Beacon(); 
     } 

     public override void Disposing() 
     { 
      if (m_Beacon != null) 
      { 
       m_Beacon.PropertyChanged -= m_Beacon_PropertyChanged; 
      } 

      base.Disposing(); 
     } 

     private void m_Beacon_PropertyChanged(
      object i_Sender, 
      System.ComponentModel.PropertyChangedEventArgs i_EventArgs) 
     { 
      OnPropertyChanged(nameof(Beacon)); 
     } 
    }