【问题标题】:How would you know which element of an ItemsControl sends an event in MVVM?您如何知道 ItemsControl 的哪个元素在 MVVM 中发送事件?
【发布时间】:2011-08-10 15:12:35
【问题描述】:

假设我目前有一个 ItemsControl,其 DataTemplate 是一堆按钮。我正在连接这些按钮的点击事件,但我怎么知道点击了哪个按钮?我不应该使用 ItemsControl 吗?

我试图不使用代码隐藏,但务实可能是必要的。

<ItemsControl>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Margin="10">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding ItemsControlButtonClicked, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    如果你想知道点击了什么Item,然后将{Binding } 作为CommandParameter 传递,它会将选定的对象传递给你的命令

    如果您想知道点击了什么 Button,我会在代码隐藏中执行此操作,因为 ViewModel 不需要了解有关 UI 的任何信息,其中包括按钮。

    此外,由于您的控件是 Button,因此您应该使用 Command 属性而不是 Click 触发器。

    <Button Command="{Binding ItemsControlButtonClicked}" />
    

    【讨论】:

    • 并且可以直接在Button上设置Command\CommandParameter属性(不带EventTrigger)达到同样的效果
    • 这似乎是我正在寻找的,但由于某种原因,该命令没有被调用。命令位于数据模板中的事实是否会更改数据上下文? Intellisense 也无法解析命令的符号。
    • 它试图执行的命令是ItemsControl.Items[X].ItemsControlButtonClicked,它的类型应该是ICommand。如果您的命令在此处不存在,则需要更改绑定。我没有使用过 MVVMLight 的交互触发器,所以我无法告诉您为什么会收到智能感知错误,但您可能需要查看他们的文档。
    • 另外,既然您使用的是 Button 控件,为什么不直接使用 Command 属性而不是 click 事件呢?请参阅我的答案的编辑。
    • 没有理由;没想到我想要的事件(单击)是 Command 的默认值。问题是我要引发的事件在 UserControl 的 DataContext 中。我试图进行绑定以在那里调用它,但它似乎不起作用。
    【解决方案2】:

    您可以将参数与命令一起发送,并根据这些参数找出单击了哪个按钮

    【讨论】:

      【解决方案3】:

      在我的项目中,我还使用了 MVVM Light 我有一个包含项目集合的下拉菜单,以及一个用户按下和操作取决于下拉菜单中选定项目的按钮 你应该创建一个带有参数的 Relay 命令,看看我的代码中的例子

        public RelayCommand<Project> StartTimer { get; private set; }//declare command
      
         StartTimer = new RelayCommand<Project>(OnStartTimer);
      
          private void OnStartTimer(Project project)
          {
      
              if (project != null)
              {
      
                  currentProject = project;
      
                  if (!timer.IsTimerStopped)
                  {
                      timer.StopTimer();
                  }
                  else
                  {
                      Caption = "Stop";
                      timer.StartTimer();
                  }
              }
      

      在视图上,我将下拉列表与类 Project 的集合绑定 对于按钮命令参数,我绑定了选定的项目表单下拉 看代码

         <ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}"    IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
                    SelectedValuePath="Name"  SelectedIndex="0"  >
          </ComboBox>
            <Button Name="timerButton" Content="{Binding Path=Caption}" Command="{Binding Path=StartTimer}" 
                      CommandParameter="{Binding ElementName=projectcomboBox, Path=SelectedItem}"  ></Button>
      

      注意Command和CommandParameter绑定

      你也可以使用这种方法不仅用于下拉

      【讨论】:

        【解决方案4】:

        好吧,您可以使用作为实际数据的 Sender.DataContext。

        【讨论】:

          【解决方案5】:

          在您的视图模型类中创建命令属性(使用 Josh Smith 的 RelayCommand 模式是最简单的方法)并将每个按钮的 Command 绑定到相应的按钮。这不仅操作简单且易于维护,还为您提供了一种在需要时实现启用/禁用行为的简单方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-13
            • 1970-01-01
            • 2021-07-03
            • 2012-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多