我有ItemsControl
,因此我可以显示同一模板的多个实例。我需要能够在事件处理程序上执行代码,以便我可以区分控件。
例如:我有一份杂货清单,因此我的DataTemplate
包含"购买"每种食物Button
。我想将所述按钮绑定到代码并告诉按下了哪个按钮。
考虑到我使用 MVVM设计模式
,我怎样才能做到这一点** XAML:**
<ItemsControl ItemsSource="{Binding MyItemList}">
<ItemsControl.ItemsTemplate>
<DataTemplate>
<Button Content="Buy" />
</DataTemplate>
</ItemsControl.ItemsTemplate>
</ItemsControl>
因此,MyItemList
是List<MyItem>
个实例。 DataTemplate
包含修改值或执行MyItem
中不存在的代码的控件:
我已经阅读了很多关于将模板命名为命令的文章,但我找不到一个使用项目列表的文章。
答案 0 :(得分:4)
您需要将Button绑定到Command的ItemsControl的DataContext。
在WPF中搜索命令:(通用实现):
public class RelayCommand<T> : IRelayCommand
{
private Predicate<T> _canExecute;
private Action<T> _execute;
public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
private void Execute(T parameter)
{
_execute(parameter);
}
private bool CanExecute(T parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public bool CanExecute(object parameter)
{
return parameter == null ? false : CanExecute((T)parameter);
}
public void Execute(object parameter)
{
_execute((T)parameter);
}
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
var temp = Volatile.Read(ref CanExecuteChanged);
if (temp != null)
temp(this, new EventArgs());
}
}
在你的ViewModel中(ItemsControl的DataContext,我希望:))
private RelayCommand<FoodItem> _addToGroceriesCommand;
public ICommand AddToGroceriesCommand
{
get
{
if (_addToGroceriesCommand == null)
{
_addToGroceriesCommand = new RelayCommand<FoodItem>(OnAddToGroceries);
}
return _addToGroceriesCommand;
}
}
public void OnAddToGroceries(FoodItem newItem)
{
}
XAML:
<ItemsControl ItemsSource="{Binding MyItemList}">
<ItemsControl.ItemsTemplate>
<DataTemplate>
<Button Content="Buy"
Command="{Binding Path=DataContext.AddToGroceriesCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}" />
</DataTemplate>
</ItemsControl.ItemsTemplate>
</ItemsControl>
答案 1 :(得分:3)
你永远不应该在DataTemplates中使用事件,这将使你使用转换然后在整个MVVM模式中打洞。按钮具有Command属性,您应该将该属性绑定到MyItem ViewModel中的命令。
如果你仍然需要使用一个事件(例如你不能将MouseDown绑定到命令),你应该使用EventToCommadn Behavior,它允许你将事件绑定到命令。您可以在此处阅读:http://msdn.microsoft.com/en-us/magazine/dn237302.aspx
答案 2 :(得分:-1)
你可能会做几件事。
<Button Content="Add" Click={Click} Tag="{Binding .}" DataContext="{Binding .}" />
DataContext =“{Binding。} - 将整个VM实例设置为属性。您可以使用Tag属性执行相同操作。有时,将Tag用于这些目的非常有用。您可以使用其中任何一个。工作
public void Click(...)
{
var control = sender as FrameWorkElement;
if(control!= null)
{
var myVM = control.DataContext as MyViewModel;
myVM.DoSomethingWithMyVM();
}
}
您可以创建包含网格的用户控件,并在网格中引用自定义用户控件。这非常灵活。在它的ButtonEventhandler中,您可以访问datacontext并使用它执行您需要的操作。这样做要容易得多,但是你可以通过parrent对象获得更多的工作。如果要重用此控件,这样会更好。
您可以做的另一件事是将按钮的datacontext设置为整个ViewModel。最后的努力解决方案是将按钮的标签设置为整个ViewModel。如果您不打算重复使用它,那就更好了。
您也可以将其用作resourceDictionary的资源。