2013-08-02 8 views
5

Riferimento alla domanda: (Is there a pattern for subscribing to hierarchical property changes with Reactive UI?)esiste un modo per iscriversi a tutte le modifiche di proprietà hierachical con l'interfaccia utente reattiva?

Attualmente ho un bambino reattivooggetto nel mio genitore reattivooggetto.

public class Child : ReactiveObject 
{ 
private string propertyX 
public string PropertyX 
    { 
     get { return this.propertyX; } 
     set { this.RaiseAndSetIfChanged(x => x.PropertyX, ref this.propertyX, value); } 
    } 

private string propertyY 
public string PropertyY 
    { 
     get { return this.propertyY; } 
     set { this.RaiseAndSetIfChanged(x => x.PropertyY, ref this.propertyY, value); } 
    } 
} 

public class Parent: ReactiveObject 
{ 

public Parent(Child child) 
{ 
    Child = child; 
    this.WhenAny(x => x.Child.PropertyX, x => x.Value).Subscribe(x => raisePropertyChanged("Child")); 
} 

private Child child 
public Child Child 
    { 
     get { return this.child; } 
     set { this.RaiseAndSetIfChanged(x => x.Child, ref this.child, value); } 
    } 
} 

La mia domanda è che cosa devo scrivere:

this.WhenAny(x => x.Child.PropertyX, x => x.Value).Subscribe(x => raisePropertyChanged("Child")); 

per ogni proprietà bambino?

Il motivo per cui è necessario eseguire questa operazione è perché la griglia DevExpress non si aggiorna a causa del bind della proprietà nidificata.

<dxg:GridColumn x:Key="PropertyX" Header="PropertyX" FieldName="Child.PropertyX" /> 
+0

Puoi spiegare l'ultima parte di più? Non è chiaro che cosa si sta tentando di fare con DevExpress Grid –

+0

La griglia DevExpress non aggiorna gli elementi framework che hanno un bind nested. Quindi devo creare una sottoscrizione WhenAny per propagare l'inotifypropetychanged. È una limitazione da parte loro che mi chiedo se ReactiveUI abbia una soluzione intelligente per questo. Questo lo spiega? – JugheadNY

risposta

1

così, è un po 'di un hack, ma si può sempre "avanti" una proprietà:

this.WhenAny(x => x.Child.PropertyX, x => x.Value).ToProperty(this, x => x.PropertyXFromChild, out propertyXFromChild); 
+0

Wont questo implica che devo avvolgere la proprietà annidata nel genitore? Dovrei creare una proprietà chiamata PropertyXFromChild. – JugheadNY

+0

Sì, ma se DevExpress non capirà in nessun altro modo, non vedo cos'altro si può fare .. –

0

Si potrebbe provare qualcosa con alberi di espressione. Questo ha funzionato per me fino a quando (penso) un recente cambiamento in RxUI6. Per ora funziona per determinati tipi di proprietà.

void Main() 
{ 
    var o1 = new ReactivePerson(); 

    foreach (var element in Functions.GetProperties<ReactivePerson>()) 
    { 
     o1.ObservableForProperty(element).Subscribe(x=>string.Format("property: {0} is changing to {1}", x.GetPropertyName(), x.Value).Dump()); // note that the Dump() method is for LinqPad (http://www.linqpad.net/). Use console.log or similar if needed. 
    } 

    // Both properties registered 
    o1.FirstName = "Jenny"; 
    o1.FirstName = "Peter"; 
    o1.FirstName = "Dave"; 
    o1.LastName = "Peterson"; 
    o1.LastName = "Jones"; 
    o1.LastName = "Smith"; 
} 

public static class Functions{ 
    public static IList<Expression<Func<T,object>>> GetProperties<T>() 
    { 
     var result = new List<Expression<Func<T,object>>>(); 
     var properties = typeof(T).GetProperties().Where(pi => pi.GetCustomAttributes(typeof(DataMemberAttribute), false).Any()); 
     foreach (var property in properties) 
     { 
      var p = Expression.Parameter(typeof(T), "p"); 
      //var prop = Expression.Convert(Expression.Property(p, property), typeof(Object)); 
      // Note I think that you should use the expression.convert line, which allows you to handle Int32s etc. However, I 'think' that there's a but in RxUI6 which is blocking it. https://github.com/reactiveui/ReactiveUI/issues/659 
      var prop = Expression.Property(p, property); // try this instead 
      var keySelector = Expression.Lambda<Func<T, object>>(prop, p); 
      result.Add(keySelector); 
     } 
     return result; 
    } 
} 
public class ReactivePerson : ReactiveObject 
{ 

     [IgnoreDataMember] 
     string _firstName; 
     [DataMember] 
     public string FirstName{ 
      get { return _firstName; } 
      set { this.RaiseAndSetIfChanged(ref _firstName, value); } 
     } 

     [IgnoreDataMember] 
     string _lastName; 
     [DataMember] 
     public string LastName{ 
      get { return _lastName; } 
      set { this.RaiseAndSetIfChanged(ref _lastName, value); } 
     } 

//  int not working, see comment in Functions.GetProperties.   
//  [IgnoreDataMember] 
//  int _age; 
//  [DataMember] 
//  public int Age{ 
//   get { return _age; } 
//   set { this.RaiseAndSetIfChanged(ref _age, value); } 
//  } 
} 
Problemi correlati