2014-09-16 9 views
10

Ich habe einige Probleme mit dem RelayCommand von GalaSoft.RelayCommand funktioniert nach einer Weile

Ich habe eine NextCommand Eigenschaft, die funktioniert, aber nur einige Male.

Danach hört es vollständig auf zu arbeiten.

Sie können dies mit dem Beispielprojekt ausprobieren:

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

Das Verhalten ist wie folgt:

  1. nextcommand:
    1. Pops alle Elemente bis zum aktiven Index
    2. , wenn es weniger als 50 Stück links, drückt 1 neues Element
    3. Marken neues Objekt als aktive
  2. BackCommand:
    1. den aktiven Index zurück um 1 Position bewegt

Schritte zu replizieren:

  1. die ‚+‘ (OEMplus) Schlüssel wurde an nextcommand gebunden
  2. der ‚-‘ (OemMinus) Schlüssel wurde BackCommand gebunden
  3. Halten Sie die ‚+‘ drücken, bis die Liste aufhört zu wachsen (50 Titel begrenzen)
  4. die Hold ‚-‘ drücken, bis der erste Eintrag in der Liste dem aktiv
  5. Repeat ist

die Anzahl der Wiederholungen benötigt (um den Fehler zu replizieren) ist inkonsistent.

Manchmal bekomme ich es nach 4 Wiederholungen; up anderen Zeiten bis 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; } 
} 

Als ich in den RelayCommand Code trat, die -Aktion ausführen IsAlive Flag falsch war. Aber ich kann mir nicht vorstellen, wie das passieren könnte.

+4

+1 für Ihr nettes animiertes Gif, das Ihr Problem erklärt. – Sheridan

+2

Ich sehe nicht, wo 'NextCommand' in Ihrem Code instanziiert ist. Das Problem könnte da sein (etwas, was es deaktiviert). – Sinatr

+1

Mit anderen Worten, wir müssen sehen, was 'NextCommand' ist – Kcvin

Antwort

10

Zwei Worte: Garbage Collector

In Ihrem Beispiel-Projekt - mit dem Sie die entsprechenden Bits schreiben sollte Ihre Frage zukunftssicher zu machen - stellen Sie die DataContext auf Ihrem Fenster wie folgt aus:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     var logic = new LogicObject(); 
     DataContext = logic.Collection; 
    } 
} 

Da nichts anderes einen Verweis auf die hier erstellten LogicObject enthält, wird es bei der nächsten Gelegenheit gesammelt werden.

Die Anschläge Befehl, weil in LogicObject funktioniert, stellen Sie die NextCommand der ItemCollection private Mitglieder des bald-zu-sein-gesammelt verwenden LogicObject:

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

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

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

Sobald LogicObject gesammelt wird, kann der Befehl nicht länger arbeiten, weil es keine Verweise auf gültige Methoden mehr hat (AddItem und CanAddItem). Dies ist der Grund, warum das isAlive Feld auf den beiden RelayCommand schwachen Referenzen auf die Methoden falsch ist.

Sie können dies beheben, indem Sie einfach an die LogicObject hängen, oder indem Sie die AddItem und CanAddItem Methoden in die Sammlung verschieben.


für diese Frage im Geist der GIFs zu bekommen, hier ist eine, die die Taste los, sobald eine 0 Sammlung Gen stoppen zeigt Arbeiten auftritt.

Desktop capture showing button failing when GC occurs

+0

Ich sehe es jetzt. Ich wusste immer, dass RelayCommand WeakActions und WeakReferences verwendet, aber ich vermisste immer noch den Teil, in dem mein LogicObject nirgendwo anders referenziert wurde. Danke für die Antwort! (und tolles gif btw) – jayars

1

warum nicht nutzen Sie einfach die Methoden von ICollectionView? haben Sie da:

  • MoveCurrentTo
  • MoveCurrentToFirst
  • MoveCurrentToLast
  • MoveCurrentToNext
  • MoveCurrentToPrevious
  • und andere nette Sachen

so etwas wie dieses

private ICollectionView MyView {get;set;} 


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


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

hi blindmeis. Ich war nicht wirklich auf der Suche nach Sammelaktionen. Ich habe zufällig die Beispielklassen ItemCollection und Item benannt. Der wichtigste Teil des Codes ist die NextCommand-Eigenschaft, die von ihrem Aufrufer konfiguriert werden kann. – jayars