我在使用GalaSoft的RelayCommand时遇到了一些问题。
我有一个 NextCommand 属性,但只能运行几次。
之后,它完全停止工作。
您可以尝试使用示例项目:
http://s000.tinyupload.com/?file_id=65828891881629261404
行为如下:
复制步骤:
所需的重复次数(复制错误)不一致。
有时我会在重复4次后得到它;其他时间到9点。
// 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。但我似乎无法弄清楚这可能会如何发生。
答案 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...
}
}
后,该命令将无法再运行,因为它不再引用有效方法(LogicObject
和AddItem
)。这就是为什么CanAddItem
对方法的弱引用的isAlive
字段都是错误的。
您可以通过暂停RelayCommand
或将LogicObject
和AddItem
方法移至集合中来解决此问题。
为了解决这个问题的GIF精神,这里有一个显示Gen 0收集发生时按钮停止工作的那个。
答案 1 :(得分:1)
为什么不简单地使用ICollectionView中的方法?你有:
类似这样的事情
private ICollectionView MyView {get;set;}
this.MyView = CollectionViewSource.GetDefaultView(this._items);
if (!this.MyView.IsCurrentBeforeFirst)
{
this.MyView.MoveCurrentToPrevious();
}