【问题标题】:Pass the item DataContext in CommandParameter在 CommandParameter 中传递项 DataContext
【发布时间】:2012-12-14 02:17:47
【问题描述】:

我有一个树视图,它是从 SecondViewModel 实例中的 ItemsSource 创建的,与我的 Window DataContext 不同。

我想通过 `CommandParameter 发送属于 TreeViewItem 的 ViewModel。

窗口数据上下文是:MyViewModel。 treeviewitems 数据上下文为:SecondViewModel

我想传递 SecondViewModel 而不是 MyViewModel

因此,

CommandParameter ="{Binding}" 

不起作用(因为它会发送MyViewModel

编辑:一些代码:

 <TreeView Name="treeView" ItemContainerStyle="{StaticResource TreeViewItemStyle}"  Grid.Row="1" Grid.Column="1">
        <TreeViewItem Header="{Binding ProjectName}">
            <TreeViewItem commandBehaviors:MouseDoubleClick.Command="{Binding SelectOtherTab}" 
                          commandBehaviors:MouseDoubleClick.CommandParameter="{Binding}" //this returns the data context of the window, I want to return the Item Source
                ContextMenu="{StaticResource AddClassMenu}" ItemTemplate="{DynamicResource ClassDataTemplate}" ItemsSource="{Binding ClassCollection}">

如何发送SecondViewModel

编辑:

我想启用删除当前项目,但由于某种原因该命令永远不会被调用。

代码如下:

<TreeViewItem x:Name="treeViewItem"
                ContextMenu="{StaticResource AddClassMenu}" ItemTemplate="{DynamicResource ClassDataTemplate}" ItemsSource="{Binding ClassCollection}">
                <TreeViewItem.ItemContainerStyle>
                    <Style TargetType="TreeViewItem">
              HERE->>          <Setter Property="ContextMenu" Value="{StaticResource RemoveClassMenu}"/>
                        <Setter Property="commandBehaviors:MouseDoubleClick.Command" 
        Value="{Binding ElementName=treeViewItem, Path=DataContext.SelectOtherTab}" />
                        <Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" 
        Value="{Binding }" />
                    </Style>
</TreeViewItem>

我的上下文菜单:

 <ContextMenu x:Key="RemoveClassMenu">
    <MenuItem Header="Delete" Command="{Binding ElementName=treeViewItem, Path=DataContext.RemoveClass}" CommandParameter="{Binding}"/>
</ContextMenu>

如前所述,该命令永远不会被调用。我的代码有什么问题?

【问题讨论】:

  • 请问为什么要在CommandParameter中绑定整个ItemSource?以及如何设置 TreeView 的 ItemSource。
  • 我对您的SecondViewModel 与您的MyViewModel 的关系以及ItemsSource 的来源有点困惑。您能否包含更多代码来显示这 3 个如何相互关联?如果您使用ItemsSource 属性而不是手动定义每个TreeViewItem 来构建TreeView,那么您可以在ItemContainerStyle 中设置您的命令行为,{Binding } 将引用ItemsSource 中的每个项目。现在,我根本看不到您的 SecondViewModel 在您的代码中的位置。
  • @MatsMagnem 我不想要整个 ItemSource,只想要与 treeviewitem 相关的那个。 (1 项)
  • @Rachel 对不起,我说'SecondViewModel'只是为了更容易理解,它实际上是ItemSource - ClassCollection,ClassCollection是从ClassViewModel创建的observablecollection(这实际上是SecondViewModel 我之前用作示例)。
  • @idish 你不能使用{Binding ClassCollection} 而不是{Binding } 来传递你的SecondViewModel 吗?

标签: c# wpf command


【解决方案1】:

我认为您要做的是将DoubleClick 命令设置在您的孩子TreeViewItems 上,而不是您的父母TreeViewItem 设置ItemsSource

现在,您的 XAML 说要构建一个父 TreeViewItem,然后在此之下为 ClassCollection 中的每个项目构建一组子 TreeViewItems。当您双击父 TreeViewItem 然后运行 ​​SelectOtherTab 命令时,没有任何内容可以指定点击了哪个子 TreeViewItem

这是您现在拥有的 XAML 的简化视图。

<TreeView x:Name="treeView">
    <TreeViewItem OnDoubleClick="SelectOtherTab"> <!-- Parent TreeViewItem -->
        <TreeViewItem /><!-- Child TreeViewItems -->
        <TreeViewItem />
        <TreeViewItem />
        ...
    </TreeViewItem>
</TreeView>

相反,您希望将CommandCommandParameter 属性附加到每个子TreeViewItem,如下所示:

<TreeViewItem.ItemContainerStyle>
  <Style TargetType="TreeViewItem">
    <Setter Property="commandBehaviors:MouseDoubleClick.Command" 
            Value="{Binding ElementName=treeView, Path=DataContext.SelectOtherTab}" />
    <Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" 
            Value="{Binding }" />
  </Style>
</TreeViewItem.ItemContainerStyle>

这将使您的简化 XAML 看起来像这样:

<TreeView x:Name="treeView">
    <TreeViewItem> <!-- Parent TreeViewItem -->
        <TreeViewItem OnDoubleClick="SelectOtherTab" /><!-- Child TreeViewItems -->
        <TreeViewItem OnDoubleClick="SelectOtherTab"/>
        <TreeViewItem OnDoubleClick="SelectOtherTab" />
        ...
    </TreeViewItem>
</TreeView>

我仍然有点困惑为什么你有一个父 TreeViewItem 并且正在使用它的 TreeViewItems 构建子 ItemsSource,但是如果这不是必需的,你可以通过消除父 TreeViewItem 来简化你的 VisualTree这个:

<TreeView Name="treeView" 
          ItemsSource="{Binding ClassCollection}"
          ItemContainerStyle="{StaticResource TreeViewItemStyle}"  
          Grid.Row="1" Grid.Column="1">
    <TreeView.Resources>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="Header" Value="ProjectName" />
            <Setter Property="ContextMenu" Value="{StaticResource AddClassMenu}" />
            <Setter Property="ItemTemplate" Value="{DynamicResource ClassDataTemplate}" />

            <Setter Property="commandBehaviors:MouseDoubleClick.Command" 
                    Value="{Binding ElementName=treeView, Path=DataContext.SelectOtherTab}" />
            <Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" 
                    Value="{Binding }" />
        </Style>
    </TreeView.Resources>
</TreeView>

这将使您的 TreeView 看起来像这样:

<TreeView x:Name="treeView">
    <TreeViewItem OnDoubleClick="SelectOtherTab" />
    <TreeViewItem OnDoubleClick="SelectOtherTab"/>
    <TreeViewItem OnDoubleClick="SelectOtherTab" />
    ...
</TreeView>

【讨论】:

  • 哇,我真的很感谢你帮助我的努力,谢谢!我很抱歉..我想我犯了一个错误..这导致你给我一个我不想要的东西的解决方案。我不希望只有父 treeviewitem 能够点击,我想要相反,我想让它的所有子项能够点击并执行命令。这样,每个树视图项(子项)都是从 ClassCollection 项构建的。我只想传递对项目“负责”的 ViewModel。再次感谢您,抱歉我的英语不好,如果有什么不明白的地方请告诉我
  • @idish 我想是这样 :) 我发布的代码将使得从ClassCollection 生成的每个TreeViewItem 都会有一个调用SelectOtherTab 的doubleClick 事件,并传递项目从ClassCollection in 作为参数
  • 那么是的。伟大的!我打算过几次试试。顺便说一句,关于你关于树视图的最后一个提示,我没有这样做,因为我有另一组 TreeViewItem(我只显示了必要的代码)。
  • @idish 我想知道是不是因为你的Header 绑定。让我知道它是怎么回事:)
  • 它正在工作!!!非常感谢你,真的,你帮助我更多地了解了 WPF 的工作原理。我对此很陌生,我大约在 2 周前开始。无论如何,非常感谢!
【解决方案2】:

您必须在 MyViewModel 中声明 SecondViewModel 类型的属性。然后您也可以将数据绑定到内部项目。

CommandParameter="{Binding SecondViewModelProp.CommandParam}"

如果命令参数在 SecondViewModelProp 中定义。

如果我理解错了,请告诉我。

 public class MyViewModel
 {
    public SecondViewModel  SecondViewModelProp
    {
        get { return new SecondViewModel(); }
    }

   public MyViewModel()
   {

   }
 }

【讨论】:

  • 如果我要声明 SecondViewModel 类型的属性,如何将它绑定到我的 treeviewitem 的命令参数?
  • 嗯,抱歉,不太明白。什么是 SecondViewModelProp?该物业将做什么?什么是 CommandParam?
  • SecondViewModelProp 是 myViewModel 中 SecondViewModel 的属性。
  • 但它会返回什么?我想返回当前的 SecondViewModel(负责 treeviewitem 的那个)
  • 啊,抱歉挖掘太多,但我想在尝试之前了解,获得新的 SecondViewModel 对我有什么帮助?我想返回当前现有的 SecondViewModel。(它已经在 observableCollection 中)
猜你喜欢
  • 2016-02-05
  • 2011-01-20
  • 1970-01-01
  • 2016-11-24
  • 2017-08-06
  • 1970-01-01
  • 2016-04-27
  • 2015-02-14
  • 1970-01-01
相关资源
最近更新 更多