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。

在此处输入图像描述

// Items Collection public class ItemCollection : ViewModelBase { // List of Items private readonly ObservableCollection _items = new ObservableCollection(); public ObservableCollection 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标志为false。 但我似乎无法弄清楚这可能会如何发生。

两个字: 垃圾收集器

在您的示例项目中 – 您应该发布相关的部分以使您的问题面向未来 – 您在窗口上设置DataContext ,如下所示:

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var logic = new LogicObject(); DataContext = logic.Collection; } } 

因为没有其他内容保留对LogicObject创建的LogicObject的引用,所以将在下一次机会时收集它。

该命令停止运行,因为在LogicObject ,您将ItemCollectionNextCommand设置为使用即将收集的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 ,该命令将无法再运行,因为它不再引用有效方法( AddItemCanAddItem )。 这就是为什么RelayCommand对这些方法的弱引用的isAlive字段都是错误的。

您可以通过挂起LogicObject或将AddItemCanAddItem方法移动到集合中来解决此问题。


为了获得这个问题的GIF精神,这里显示了一旦Gen 0收集发生时按钮停止工作。

GC发生时,桌面捕获显示按钮失败

为什么不简单地使用ICollectionView中的方法? 你有:

  • MoveCurrentTo
  • MoveCurrentToFirst
  • MoveCurrentToLast
  • MoveCurrentToNext
  • MoveCurrentToPrevious
  • 和其他好东西

这样的事情

  private ICollectionView MyView {get;set;} this.MyView = CollectionViewSource.GetDefaultView(this._items); if (!this.MyView.IsCurrentBeforeFirst) { this.MyView.MoveCurrentToPrevious(); }