一段时间后,RelayCommand停止工作

时间:2014-09-16 11:59:29

标签: c# wpf mvvm-light relaycommand

我在使用GalaSoft的RelayCommand时遇到了一些问题。

我有一个 NextCommand 属性,但只能运行几次。

之后,它完全停止工作。

您可以尝试使用示例项目:

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

行为如下:

  1. NextCommand
    1. 弹出所有项目,直到活动索引
    2. 如果剩余的项目少于50个,则推送1个新项目
    3. 将新项目标记为有效
  2. BackCommand
    1. 将活动索引向后移动1个位置
  3. 复制步骤:

    1. '+'(OemPlus)键已绑定到NextCommand
    2. ' - '(OemMinus)键已绑定到BackCommand
    3. 按住“+”键直到列表停止增长(限制50个项目)
    4. 按住“ - ”键,直到列表中的第一项为活动
    5. 重复
    6. 所需的重复次数(复制错误)不一致。

      有时我会在重复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 标志为false。但我似乎无法弄清楚这可能会如何发生。

2 个答案:

答案 0 :(得分:10)

两个字:垃圾收集器

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

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

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

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

该命令停止运行,因为在LogicObject中,您将NextCommand的{​​{1}}设置为使用即将收集的ItemCollection的私有成员:< / p>

LogicObject

收集public class LogicObject { public LogicObject() { Collection = new ItemCollection(); Collection.NextCommand = new RelayCommand(AddItem, CanAddItem); AddItem(); } private bool CanAddItem() { // snip... } private void AddItem() { // snip... } } 后,该命令将无法再运行,因为它不再引用有效方法(LogicObjectAddItem)。这就是为什么CanAddItem对方法的弱引用的isAlive字段都是错误的。

您可以通过暂停RelayCommand或将LogicObjectAddItem方法移至集合中来解决此问题。


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

Desktop capture showing button failing when GC occurs

答案 1 :(得分: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();
 }