2012-10-02 13 views
5

Il mio progetto è basato sul pattern MVVM.Come aggiornare l'interfaccia utente in MVVM WPF

Ho costruito una vista ad albero che mostra il mio file system. Ogni cartella ha una casella per selezionare la cartella corrente. Il processo di selezione richiede un po 'di tempo, mentre l'operazione è in esecuzione, c'è un pulsante che è disabilitato e al termine dell'operazione sto abilitando il pulsante.

Il mio problema è che quando il pulsante diventa "disabilitato" lo vedo immediatamente. Tuttavia, quando il pulsante ritorna alla modalità abilitata, devo agire (come il clic del mouse) per vedere il pulsante abilitato.

Come posso verificare che l'interfaccia utente venga aggiornata immediatamente dopo l'attivazione del pulsante?

Questi sono i miei pulsanti:

<Button Content="&lt;- Back" Margin="5,0,5,0" Width="80" Height="25" 
     IsEnabled="{Binding CanMoveToPreviousPage, UpdateSourceTrigger=PropertyChanged}" 
     Command="{Binding Path=NavigateBackCommand, IsAsync=True}" /> 

<Button Content="{Binding ButtonNextCaption}" Margin="5,0,5,0" Width="80" Height="25" 
     IsEnabled="{Binding CanMoveToNextPage, UpdateSourceTrigger=PropertyChanged}" 
     Command="{Binding Path=NavigateNextCommand, IsAsync=True}" /> 

Nel mio ViewModel ho aggiunto questo codice:

public bool CanMoveToNextPage 
{ 
    get 
    { 
     return this.CurrentPage != null && this.CurrentPage.CanMoveNext; 
    } 
    set 
    { 
     if (CurrentPage != null) 
     { 
      this.CurrentPage.CanMoveNext = value; 
      OnPropertyChanged("CanMoveToNextPage"); 
     } 
    } 
} 

public bool CanMoveToPreviousPage 
{ 
    get { return 0 < this.CurrentPageIndex && CurrentPage.CanMoveBack; } 
    set 
    { 
     if (CurrentPage != null) 
     { 
      this.CurrentPage.CanMoveBack = value; 
      OnPropertyChanged("CanMoveToPreviousPage"); 
     } 
    } 
} 

aggiornare l'interfaccia utente avviene subito dopo eseguo un clic del mouse o qualsiasi combinazione di tasti.

Questo è il codice dell'azione che viene disattivazione e attivazione dei pulsanti:

void bg_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
{ 
    DecrementDoneCounter(); 
    if (ThreadSafeCouner == 0)//means all bg workers are done 
    { 
     UIlimitation(true); 
    } 
} 

private int ThreadSafeCouner; // check how many bgworkers run 
public void IncrementDoneCounter() { Interlocked.Increment(ref ThreadSafeCouner); } 
public void DecrementDoneCounter() { Interlocked.Decrement(ref ThreadSafeCouner); } 


void bg_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    IncrementDoneCounter(); 
    UIlimitation(false); 
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = false; 
    MarkItems(((bgArguments)e.Argument).SelectedDirectory, ((bgArguments)e.Argument).IsSelect); 
    ((bgArguments)e.Argument).FreeWorkerAllocation(); 
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = true; 
} 

//this is the enabling action which execute the propeties setters at the upper part of this post 
private static void UIlimitation(bool limit) 
{ 
    MainWindowViewModel.Instance.CanMoveToNextPage = limit; 
    MainWindowViewModel.Instance.CanMoveToPreviousPage = limit; 
} 

Cosa posso fare?

+1

cercano this.UpdateLayout() o ButtonsParent.UpdateLayout() –

+0

Quando l'operazione è fatta stai alzando l'evento 'OnPropertyChanged' per le proprietà interessata per attivare/disattivare il pulsante? –

+0

Quando ho finito ho cambiato la proprietà abilitata ma Set {...} e Set {} includono l'evento OnPropertyChanged. Quando provo a eseguire il debug, tutto funziona perfettamente e il pulsante viene abilitato senza fare clic. Posso capire quale sia il problema – Ofir

risposta

5

È possibile regolare il vostro controllo Binding mode TwoWay e definire triggers with PropertyChanged

{Binding ElementName=.., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} 
+0

L'ho fatto ma il problema esiste ancora. – Ofir

+0

Il modello MVVM dovrebbe implementare INotifyPropertyChanged, per inviare notifica ai controlli –

+0

L'ho già implementato – Ofir

1

Ecco un esempio di codice di come si potrebbe configurare il ViewModel con il metodo INotifyPropertyChanged di inviare messaggi per aggiornare l'interfaccia utente:

public class MyViewModel : INotifyPropertyChanged 
{ 
    /******************************************************/ 
    /* Property that you have created two-way binding for */ 
    /******************************************************/ 
    private double _myProperty 
    public double MyProperty 
    { 
     get { return _myProperty; } 
     set 
     { 
      _myProperty = value; 

      OnNotifyPropertyChanged("MyProperty"); 
     } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnNotifyPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion INotifyPropertyChanged Members 
} 
+1

Ciao, Il mio progetto contiene già questo codice. – Ofir

+0

Verificare il valore di OnNotifyPropertyChanged ("MyProperty"); è giusto. –

1

OK Ho trovato una soluzione.
Ho provato di tutto senza successo e alla fine ho trovato questa discussione: Refresh WPF Command

ho usato CommandManager.InvalidateRequerySuggested()

e le sue opere.

Grazie per il vostro aiuto