2014-09-16 14 views
10

Sto riscontrando alcuni problemi nell'uso di RelayCommand di GalaSoft.RelayCommand smette di funzionare dopo un po '

I have a NextCommand proprietà che funziona, ma solo più volte.

Successivamente, smette di funzionare completamente.

Si può provare questo con il progetto di esempio:

http://s000.tinyupload.com/?file_id=65828891881629261404

Il comportamento è la seguente:

  1. nextCommand:
    1. pops tutti gli elementi fino alla attiva indice
    2. se vi sono meno di 50 elementi di sinistra, spinge 1 nuovo elemento
    3. marchi new come attivo
  2. BackCommand:
    1. sposta l'indice attivo indietro di 1 posizione

Passi per la replica:

  1. il tasto '+' (OemPlus) è stato legato a nextCommand
  2. il tasto '-' (OemMinus) è stato legato a BackCommand
  3. Tenere premuto il tasto '+' fino a quando l'elenco smette di crescere (50 articoli limitano)
  4. Tenere il tasto '-' fino alla prima voce dell'elenco è la attiva
  5. Ripetere

il numero di ripetizioni necessarie (per replicare il bug) è incoerente.

A volte capisco dopo 4 ripetizioni; altre volte fino fino a 9.

enter image description here

// Items Collection 
public class ItemCollection : ViewModelBase 
{ 
    // List of Items 
    private readonly ObservableCollection<Item> _items = new ObservableCollection<Item>(); 
    public ObservableCollection<Item> Items 
    { 
     get { return _items; } 
    } 

    // Constructor 
    public ItemCollection() 
    { 
     BackCommand = new RelayCommand(
       () => 
       { 
        // Go to previous page 
        var index = Items.IndexOf(ActiveItem); 
        if (index > 0) 
        { 
         ActiveItem = Items[index - 1]; 
        } 
       }, 
       () => ActiveItem != null && Items.IndexOf(ActiveItem) > 0); 
    } 

    // Back command 
    public RelayCommand BackCommand { get; set; } 

    // Next command 
    public RelayCommand NextCommand { get; set; } 

    // The currently-active item 
    private Item _activeItem; 
    public Item ActiveItem 
    { 
     get { return _activeItem; } 
     set 
     { 
      Set(() => ActiveItem, ref _activeItem, value); 
     } 
    } 
} 

// Item 
public class Item : ViewModelBase 
{ 
    public string Title { get; set; } 
} 

Quando ho fatto un passo in codice del RelayCommand, isAlive bandiera della azione di esecuzione era falsa. Ma non riesco a capire come possa accadere.

+4

+1 per il tuo bel Gif animato che spiega il tuo problema. – Sheridan

+2

Non vedo dov'è 'NextCommand' istanziato nel codice. Il problema potrebbe essere lì (qualcosa che lo disabilita). – Sinatr

+1

In altre parole, dobbiamo vedere cosa 'NextCommand' è – Kcvin

risposta

10

Due parole: Garbage Collector

Nel progetto di esempio - che si dovrebbe inviare i bit rilevanti di per rendere il vostro futuro a prova di domanda - si imposta il DataContext sulla vostra finestra come questa:

Poiché nient'altro conserva un riferimento allo LogicObject creato qui, verrà raccolto alla prossima occasione.

Le fermate dei comandi di funzionamento perché in LogicObject, è possibile impostare la NextCommand del ItemCollection di utilizzare membri privati ​​della soon-to-be-raccolti LogicObject:

public class LogicObject 
{ 
    public LogicObject() 
    { 
     Collection = new ItemCollection(); 
     Collection.NextCommand = new RelayCommand(AddItem, CanAddItem); 
     AddItem(); 
    } 

    private bool CanAddItem() 
    { 
     // snip... 
    } 

    private void AddItem() 
    { 
     // snip... 
    } 
} 

volta LogicObject viene raccolto, il comando non può lavoro più lungo perché non ha più riferimenti a metodi validi (AddItem e CanAddItem). Questo è il motivo per cui il campo isAlive su entrambi i deboli riferimenti ai metodi di RelayCommand è falso.

È possibile risolvere questo problema semplicemente aggrappandosi allo LogicObject o spostando i metodi AddItem e CanAddItem nella raccolta.


Per ottenere nello spirito di GIF per questa domanda, ecco uno che mostra il pulsante di smettere di lavorare non appena si verifica una raccolta Gen 0.

Desktop capture showing button failing when GC occurs

+0

Lo vedo ora. Sapeva sempre che RelayCommand utilizza WeakActions e WeakReferences, ma è comunque riuscito a perdere la parte in cui il mio LogicObject non è stato referenziato da nessun'altra parte. Grazie per la risposta! (e grande gif btw) – jayars

1

perchè non è sufficiente utilizzare i metodi da ICollectionView? il gioco è fatto:

  • MoveCurrentTo
  • MoveCurrentToFirst
  • MoveCurrentToLast
  • MoveCurrentToNext
  • MoveCurrentToPrevious
  • e altre cose belle

qualcosa di simile

0.123.
private ICollectionView MyView {get;set;} 


this.MyView = CollectionViewSource.GetDefaultView(this._items); 


if (!this.MyView.IsCurrentBeforeFirst) 
{ 
    this.MyView.MoveCurrentToPrevious(); 
} 
+0

hi blindmeis. Non stavo davvero cercando operazioni di raccolta. Mi è appena capitato di nominare le classi di esempio ItemCollection e Item. La parte fondamentale del codice è la proprietà NextCommand, che è configurabile dal relativo chiamante. – jayars

Problemi correlati