在我的viewmodel中,我有一个包含项目的列表(ObservableCollection)。在视图中,此列表显示在ItemsControl
中。在每一行中,都有一个“删除”按钮。我希望按钮后面的命令从列表中删除该项目。
<ItemsControl ItemsSource="{Binding myList}">
<ItemsControl.ItemTemplate>
...
<Button Command="{StaticResource myDeleteCommand}" CommandParameter="???">
Remove item
</Button>
...
</ItemsControl.ItemTemplate>
</ItemsControl>
我作为命令参数传递什么?
Binding .
)?然后我没有对命令中的列表的引用,所以我需要更改我的模型,使每个列表项包含对列表的反向引用。有什么想法吗?对我来说这似乎是一个相当常见的场景,所以我想必须有一些完善的最佳实践解决方案......
答案 0 :(得分:4)
我以这种方式实现了这样的命令,我将Item作为参数传递。命令self知道它应该在哪个列表上运行。通过在我的ViewModel中调用Delete方法的委托或命令接收其构造函数中的项目列表。
即。带代理人的命令
public sealed class SimpleParameterCommandModel<T> : CommandModel
{
private readonly Action<T> execute;
private readonly Func<T, bool> canExecute;
public SimpleParameterCommandModel(string label, string tooltip, Action<T> execute, Func<T, bool> canExecute)
: base(appCtx, dataCtx, label, tooltip)
{
if (execute == null) throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
...
}
用法:
private ICommand _DeleteCommand = null;
public ICommand DeleteCommand
{
get
{
if (_DeleteCommand == null)
{
_DeleteCommand = new SimpleParameterCommandModel<IEnumerable<DataObjectModel>> ("Delete", "Delete selection from data store",
(items) => items.ToList().ForEach(i => DeleteItem(i)),
(items) => items != null && items.Count() > 0 && AllowDelete);
}
return _DeleteCommand;
}
}
public void DeleteItem(DataObjectModel item)
{
if (item == null) { throw new ArgumentNullException("item"); }
myCollection.Remove(item.Object);
}
编辑:忘记XAML
<Button Command="{Binding DeleteCommand, ElementName=...}" CommandParameter="{Binding}">
Remove item
</Button>
答案 1 :(得分:4)
首先,我将处理ViewModel中的Command。我假设用于绑定的列表在ViewModel中,因此任何在该列表上“工作”的代码也应该在ViewModel中完成。
class MyViewModel
{
// ... Clipping rest of ViewModel class ...
private ObservableCollection<MyObject> mMyList = new ObservableCollection<MyObject>();
private ICommand mMyDeleteCommand;
public MyViewModel()
{
InitializeMyListSomehow();
mMyDeleteCommand = new MyCommandClass(
(item) => DeleteItem(item),
() => mDeleteCanExecute
);
}
public ObservableCollection<MyObject> MyList
{
get { return mMyList; }
set
{
// Some function that updates the value and implements INPC
SetProperty("MyList", ref mMyList, value);
}
}
public ICommand MyDeleteCommand
{
get { return mMyDeleteCommand; }
}
void DeleteHandler(var item)
{
int index = mMyList.Remove(item);
}
}
这些物品是否独一无二?如果是这样,您可以传递该项,并且删除命令处理程序可以查找列表中的项目。
如果这些项目不是唯一的,那么你需要做一些逻辑,这取决于预期的结果。
现在,在视图中,您的代码看起来像(注意StaticResource成为Binding):
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemTemplate>
...
<Button Command="{Binding DataContext.MyDeleteCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding}">
Remove item
</Button>
...
</ItemsControl.ItemTemplate>
</ItemsControl>