2014-08-31 15 views
6

Vorrei conoscere il modo consigliato di collegarsi a ReactiveCommand's IsExecuting.Associazione a ReactiveCommand.IsExecuting

Il problema è che l'esecuzione del comando iniziale (avviata alla fine del costruttore) non sta aggiornando il controllo WPF utilizzando IsLoading come associazione, sebbene le chiamate successive funzionino come previsto.

Update 2 Add prova codice vincolante

Questo mostra il contenuto adorner quando IsLoading vale

<ac:AdornedControl IsAdornerVisible="{Binding IsLoading}"> 
    <ac:AdornedControl.AdornerContent> 
     <controls1:LoadingAdornerContent/> 
    </ac:AdornedControl.AdornerContent> 
    <fluent:ComboBox 
     ItemsSource="{Binding Content, Mode=OneWay}" 
     DisplayMemberPath="Name" 
     SelectedValuePath="ContentId" 
     SelectedValue="{Binding SelectedContentId}" 
     IsSynchronizedWithCurrentItem="True" 
    /> 
</ac:AdornedControl> 

Aggiornamento

ho trovato questo: https://github.com/reactiveui/rxui-design-guidelines

e capito dovrei essere in grado di fare qualcosa di simile:

this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting) 
    .ToProperty(this, x => x.IsLoading); 

ma dà l'errore di compilazione:

The type arguments for method 'ReactiveUI.OAPHCreationHelperMixin.ToProperty< TObj,TRet>(System.IObservable< TRet>, TObj, System.Linq.Expressions.Expression< System.Func< TObj,TRet>>, TRet, System.Reactive.Concurrency.IScheduler)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Ho anche provato:

this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting) 
    .ToProperty<TheViewModel, bool>(this, x => x.IsLoading); 

ma ottengo l'errore di compilazione:

'System.IObservable< System.IObservable< bool >>' does not contain a definition for 'ToProperty' and the best extension method overload 'ReactiveUI.OAPHCreationHelperMixin.ToProperty< TObj,TRet>(System.IObservable< TRet>, TObj, System.Linq.Expressions.Expression< System.Func< TObj,TRet>>, TRet, System.Reactive.Concurrency.IScheduler)' has some invalid arguments

e

Instance argument: cannot convert from 'System.IObservable>' to 'System.IObservable'

originale Sotto

Il codice elencati alla fine del mio post lavori per l'associazione iniziale, accedendo alla proprietà IsLoading e suona come che prende il via un abbonamento. Ma da ulteriori letture sembra dovrei usare WhenAny e io non riesco a capire che cosa è stato messo davanti al mio naso:

ToProperty and BindTo - Get initial value without Subscribing

Aggiunta:

this.WhenAnyValue(x => x.LoadCommand.IsExecuting); 

funziona anche , ma c'è un modo migliore?

Stavo pensando di rimuovere il ObservableAsPropertyHelper in quanto non sembrano fare molto per me e facendo IsLoading una proprietà normale come:

private bool _isLoading; 

public bool IsLoading 
{ 
    get { return _isLoading; } 
    set { this.RaiseAndSetIfChanged(ref _isLoading, value); } 
} 

e fare qualcosa come il seguente, ma non viene compilato perché sta cercando di assegnare un IObservable< bool> ad un bool:

this.WhenAnyValue(x => x.LoadCommand.IsExecuting) 
    .Subscribe(x => IsLoading = x); 

codice attuale:

private readonly ObservableAsPropertyHelper<bool> _isLoading; 

public bool IsLoading 
{ 
    get { return _isLoading.Value; } 
} 

LoadCommand = ReactiveCommand.CreateAsyncTask(async _ => 
{ 
    //go do command stuff like fetch data from a database 
} 

LoadCommand.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading); 

//works if I have this line 
var startSubscription = IsLoading; 

LoadCommand.ExecuteAsyncTask(); 

risposta

3

Mi sono imbattuto in questo prima e penso che quello che stai vivendo bugie here.

ToProperty/OAPH changes

  • ObservableAsPropertyHelper no longer is itself an IObservable, use WhenAny to observe it.

  • ObservableAsPropertyHelper now lazily Subscribes to the source only when the Value is read for the first time. This significantly improves performance and memory usage, but at the cost of some "Why doesn't my test work??" confusion. If you find that your ToProperty "isn't working", this may be why.

E 'pigro, quindi è necessario iscriversi ad esso (cioè richiedere un valore dalla proprietà se si utilizza OAPH) per farlo funzionare. Questo è il motivo per cui noti che il tuo var startSubscription = IsLoading; "risolve" il problema.

Sapendo che è stato più facile per me determinare se questo fosse o meno un problema, o solo qualcosa da tenere a mente durante i miei test unitari, sapendo che nella mia applicazione queste proprietà sarebbero state associate e quindi sottoscritte, rendendolo discutibile nella pratica. Sai, l'intero "albero che cade nella foresta senza nessuno lì a sentirlo" idea.

Penso che dovresti attenersi allo ToProperty che hai, che sembra la strada da percorrere per IMHO.

6

and figured I should be able to do something like:

hai l'idea giusta, ma la sintassi è un po 'fuori, provare:

this.LoadCommand.IsExecuting 
    .ToProperty(this, x => x.IsLoading, out _isLoading); 

Se si dovesse fare questo con gli oggetti che possono cambiare (cioè hai un lungo espressione), c'è un metodo speciale chiamato WhenAnyObservable che si utilizza, invece di WhenAnyValue:

this.WhenAnyObservable(x => x.SomeObjectThatMightBeReplaced.IsExecuting) 
    .ToProperty(this, x => x.IsLoading, out _isLoading); 
+0

penso che è quello che avevo meno il presente. all'inizio della chiamata. Non sembra ancora mostrare il "caricamento" iniziale sul mio controllo associato a meno che non metti in var startSubscription = IsLoading; dopo la chiamata a ToProperty. È così che dovrei tenerlo come suggerito da jomtois? Controllo questo aggiungendo un ritardo di 10 secondi alla mia chiamata asincrona e non vedo la mia visualizzazione "caricamento" sul controllo a meno che non la aggiungo. Il binding è piuttosto semplice, ma lo aggiungerò alla domanda. – RationalDev