C# ItemsControl内DataTemplate上的事件处理程序

C# ItemsControl内DataTemplate上的事件处理程序,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个ItemsControl,可以显示同一模板的多个实例。我需要能够在事件处理程序上执行代码,以便能够区分控件 例如:我有一个杂货清单,因此我的DataTemplate为每种食物都包含一个“购买”按钮。我想把这个按钮绑定到代码上,告诉你哪个按钮被按下了 考虑到我使用的是MVVM设计模式,我如何才能做到这一点 **XAML:** <ItemsControl ItemsSource="{Binding MyItemList}"> <ItemsControl.Items

我有一个
ItemsControl
,可以显示同一模板的多个实例。我需要能够在事件处理程序上执行代码,以便能够区分控件

例如:我有一个杂货清单,因此我的
DataTemplate
为每种食物都包含一个“购买”按钮。我想把这个按钮绑定到代码上,告诉你哪个按钮被按下了

考虑到我使用的是MVVM设计模式,我如何才能做到这一点

**XAML:**

<ItemsControl ItemsSource="{Binding MyItemList}">
     <ItemsControl.ItemsTemplate>
          <DataTemplate>
              <Button Content="Buy" />
          </DataTemplate> 
     </ItemsControl.ItemsTemplate>
</ItemsControl>

因此,
MyItemList
是一个
List
实例。
DataTemplate
包含修改值或执行
MyItem
中不存在的代码的控件:


我读过很多关于将模板绑定到命令的文章,但是我找不到一篇使用项目列表的文章

您可以做几件事

<Button Content="Add" Click={Click} Tag="{Binding .}" DataContext="{Binding .}" />
  • 您可以创建包含网格的usercontrol,并在网格中引用自定义usercontrol。这很灵活。在它的ButtonVenthandler中,您可以访问datacontext并使用它执行您需要的操作。这要容易得多,但您将有更多的工作用于通知parrent对象。如果要重用此控件,这会更好

  • 您可以做的另一件事是将按钮的datacontext设置为整个ViewModel。最后一个解决方案是将按钮的标记设置为整个ViewModel。如果你不打算重用它,那就更好了

  • 您还可以将其用作resourceDictionary中的资源


  • 您永远不应该在数据模板中使用事件,这将使您使用强制转换,然后在整个MVVM模式中炸出一个洞。按钮具有Command属性,您应该将该属性绑定到MyItem ViewModel中的命令


    如果您仍然需要使用事件(例如,无法将鼠标向下绑定到命令),则应使用EventToCommadn行为,该行为允许您将事件绑定到命令。您可以在此处阅读:

    您需要将按钮绑定到ItemsControl的DataContext中的命令

    在WPF中搜索命令:(常见实现):

    公共类RelayCommand:IRelayCommand
    {
    私有谓词_canExecute;
    私人行动——执行;
    公共RelayCommand(操作执行,谓词canExecute=null)
    {
    _执行=执行;
    _canExecute=canExecute;
    }
    私有void执行(T参数)
    {
    _执行(参数);
    }
    私有布尔CanExecute(T参数)
    {
    返回_canExecute==null?true:_canExecute(参数);
    }
    公共布尔CanExecute(对象参数)
    {
    返回参数==null?false:CanExecute((T)参数);
    }
    public void Execute(对象参数)
    {
    _执行((T)参数);
    }
    公共事件处理程序CanExecuteChanged;
    public void raisecancecutechanged()
    {
    var temp=易失性读取(参考CanExecuteChanged);
    如果(温度!=null)
    temp(这是新的EventArgs());
    }
    }
    
    在ViewModel中(我希望是ItemsControl的DataContext:)

    private RelayCommand\u addtoproceriescommand;
    公共ICommand addToRoceriesCommand
    {
    得到
    {
    if(_addToGroceriesCommand==null)
    {
    _addToGroceriesCommand=新的中继命令(OnAddToGroceries);
    }
    返回_addtoproceriescommand;
    }
    }
    AddToGroceries(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> 
    
    
    
    我迷路了,不知道从哪里开始。我读过这篇文章:还有其他几篇类似的文章,但这不是我想要的。当按下列表中的某一项时,我想运行回拨代码。您能告诉我一些关于Xamarin的情况以及您在哪里工作吗。。?抱歉,似乎没有联系Stackoverflow用户的方法。。eranotz50@gmail.com,我将稍后删除此帖子
    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());
        }
    }
    
       private RelayCommand<FoodItem> _addToGroceriesCommand;
       public ICommand AddToGroceriesCommand
       {
            get
            {
                if (_addToGroceriesCommand == null)
                {
                    _addToGroceriesCommand = new RelayCommand<FoodItem>(OnAddToGroceries);                    
                }
                return _addToGroceriesCommand;
            }
        }
    
       public void OnAddToGroceries(FoodItem newItem)
       {
    
       }
    
       <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>