使用异步方法时,我遇到了MVVM的RelayCommand问题。
假设我连接到服务器以使用await关键字获取项目列表。在我得到结果后,我做一个Linq查询来过滤我想要显示的那些。之后,我创建了类型为MenuContextItem的ViewModel,它具有相同类型的Children。 MenuContextItem具有类型为RelayCommand的Command属性。在视图方面,我有一个Menu,它将ItemsSource属性绑定到ParentItem(它与可观察集合上的其他项封装)。
所有项目都正确显示但是创建async的项目不执行命令,我认为它与async和RelayCommand中使用的WeakReference有关,但我不知道为什么。
var itemsSource = await Task.Run(() => GetTheItems());
var parentItem = new MenuContextItem("Parent Item", new ObservableCollection<MenuContextItem>());
var finalItems = itemsSource.Where((e) => SOME QUERY HERE ).ToList();
foreach (var e in finalItems)
{
parentItem.Children.Add(
new MenuContextItem(
e.ItemDescription,
new Command<object>((menu) => ItemSpecificAction(e)),
true
));
}
更新:经过一些更多的测试后,似乎异步调用不是问题,但我不知道可能是什么,我有相同的代码用于手动创建其他项目,它可以作为预期
编辑:添加了MenuContextItem声明
public class MenuContextItem : BindableObject
{
#region private declarations
private string _title;
private Uri _icon;
private RelayCommand<object> _command;
private bool _isActive;
private ObservableCollection<MenuContextoItem> _children;
private Action<object> _action;
#endregion
#region initialization
public MenuContextItem(string title, Action<object> action, bool isActive)
{
Title = title;
IsActive = isActive;
_action = action;
}
.... A few other constructors
#endregion
#region properties
public string Title
{
get { return _title; }
set
{
if (_title != value)
{
_title = value;
RaisePropertyChanged(() => Title);
}
}
}
public Uri Icon
{
get { return _icon; }
set
{
if (_icon != value)
{
_icon = value;
RaisePropertyChanged(() => Icon);
}
}
}
public RelayCommand<object> Command
{
get
{
if (_command == null && _action != null)
_command = new RelayCommand<object>(_action);
return _command;
}
set
{
if (_command != value)
{
_command = value;
RaisePropertyChanged(() => Command);
}
}
}
public bool IsActive
{
get { return _isActive; }
set
{
if (_isActive != value)
{
_isActive = value;
RaisePropertyChanged(() => IsActive);
}
}
}
public ObservableCollection<MenuContextItem> Children
{
get { return _children; }
set
{
if (_children != value)
{
_children = value;
RaisePropertyChanged(() => Children);
}
}
}
#endregion
}
处理不同情况的相同代码示例:
var item = new MenuContextItem("Register", null, new RelayCommand<object>((item) => Register(item)));
更新2 :忽略这一点,我的测试错误发现如果我使用MenuContextItem的新实例分配var项目,它将按预期工作,但如果我在ObservableCollection.Add()方法中声明新的MenuContextItem,它会丢失命令。现在我只需要知道原因。我真的想弄清楚这一点。
var item = new MenuContextItem(
e.Description,
null,
new RelayCommand<object>((menu) => ItemSpecificAction(e))
);
parentItem.Children.Add(item);