2014-09-16 2 views
10

У меня возникли проблемы с использованием RelayCommand GalaSoft.RelayCommand перестает работать через некоторое время

У меня есть NextCommand свойство, которое работает, но только несколько раз.

Впоследствии он прекращает работу полностью.

Вы можете попробовать это с образцом проекта:

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

поведение выглядит следующим образом:

  1. NextCommand:
    1. хлопки все элементы до активного индекс
    2. , если есть менее 50 пунктов остались, выталкивает 1 нового пункт
    3. марок нового элемента в качестве активного
  2. BackCommand:
    1. перемещает активный индекс назад на 1 позицию

Этапы тиражирования:

  1. ключ «+» (OemPlus) был связан с NextCommand
  2. «-» ключ (OemMinus) был связан с BackCommand
  3. Удерживайте клавишу «+», пока список не перестает расти (50 шт ограничение)
  4. Удерживая «-» клавишу, пока первый элемент в списке не является активным
  5. Повторять

количество повторений, необходимых для репликации (ошибка) противоречива.

Иногда я получаю его после 4 повторений; другие времена до до 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; } 
} 

Когда я ступил в код RelayCommand, в IsAlive флаг выполнит действие было ложным. Но я не могу понять, как это может произойти.

+4

+1 для вашего приятного анимированного Gif, объясняющего вашу проблему. – Sheridan

+2

Я не вижу, где в вашем коде создается экземпляр 'NextCommand'. Проблема может быть там (что-то, что отключает ее). – Sinatr

+1

Другими словами, нам нужно увидеть, что 'NextCommand' is – Kcvin

ответ

10

Два слова: Garbage Collector

В вашем примере проекта - что вы должны размещать соответствующие биты, чтобы сделать свой вопрос на будущее доказательство - вы установите DataContext на окна, как это:

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

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

Поскольку ничего другого не содержит ссылки на созданный здесь LogicObject, он будет собран при следующей возможности.

Команда прекращает функционировать, потому что в LogicObject, вы установите NextCommand в ItemCollection использовать частные члены скоро, чтобы быть собранными LogicObject:

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

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

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

После LogicObject собирается, команда может не более длинная работа, потому что у нее больше нет ссылок на действительные методы (AddItem и CanAddItem). Вот почему поле isAlive на обеих слабых ссылках на методы 10 неверно.

Вы можете исправить это, просто повесив на LogicObject или переместив в коллекцию методы AddItem и CanAddItem.


Чтобы получить в духе GIFs на этот вопрос, вот тот, который показывает кнопку перестает работать, как только происходит Gen 0 коллекции.

Desktop capture showing button failing when GC occurs

+0

Я вижу его сейчас. Всегда знал, что RelayCommand использует WeakActions и WeakReferences, но все же удалось пропустить часть, где мой LogicObject не упоминался нигде. Спасибо за ответ! (и большой gif кстати) – jayars

1

почему бы вам не просто использовать методы из ICollectionView? у вас есть:

  • MoveCurrentTo
  • MoveCurrentToFirst
  • MoveCurrentToLast
  • MoveCurrentToNext
  • MoveCurrentToPrevious
  • и другие приятные вещи

что-то вроде этого

private ICollectionView MyView {get;set;} 


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


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

hi blindmeis. Я действительно не искал операции по сбору. Я просто назвал образцы классов ItemCollection и Item. Ключевой частью кода является свойство NextCommand, которое настраивается его вызывающим абонентом. – jayars

Смежные вопросы