【问题标题】:WPF TabControl Context menu get item right-clicked in mvvmWPF TabControl上下文菜单在mvvm中右键单击项目
【发布时间】:2015-06-15 04:35:24
【问题描述】:

我有一个将 ViewModel 列表显示为选项卡控件项的应用程序。项目列表数据绑定到父 ViewModel 上的属性。 现在我想添加一个上下文菜单来支持 每个 TabItems 的操作(而不是整个 TabControl 本身)。

这是有问题的控件:

<TabControl x:Name="Items"
                Grid.Column="2"
                Grid.Row="0"
                Margin="3,5,5,3"
                Visibility="{Binding Path=TabControlVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding DisplayName}" />
                    <Button Padding="10,0,0,0"
                            Content="X"
                            Style="{DynamicResource NoChromeButton}"
                            cal:Message.Attach="CloseTab($dataContext)" />
                </StackPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>
    </TabControl>

当我将上下文菜单代码放在 TabControl 标记中时,上下文菜单 ii 将作为一个整体注册到 TabControl。这不是我想要的行为。

如果我将它添加到 DataTemplate 标签内的 StackPanel 标签中,则为每个 Item 注册的 DataTriggers 将在子 ViewModel 上执行,但视图模型没有执行事件的方法和属性。

有没有可能解决这个问题?如何为每个项目添加上下文菜单以支持以下操作:“关闭此”、“保存此”、“关闭除此之外的所有内容”


更多信息: 我使用 Caliburn.Micro 作为框架,并使用它的约定将 TabControl 绑定到 ViewModel 上的 Items 属性,这是通过从 Conductor&lt;LocationDetailsViewModel&gt;.Collection.OneActive 继承我的 ViewModel 创建的 IObservableCollection&lt;LocationDetailsViewModel&gt;LocationsDetailsViewModel 也继承自 Screen

一切都按预期进行。如果我将一个项目添加到 Items 属性,TabControl 会正确更新。 我想将ContextMenu 添加到每个 TabControl 项目,可以通过右键单击标题来访问。然后上下文菜单应包含操作,例如“关闭此”、“保存此”、“关闭除此之外的所有内容” 为此,我在StackPanel 中添加了一个上下文菜单,它控制标题的设计,并使用 CM 在视图模型上调用适当的方法。但是当我调用它时,我得到一个异常,告诉我找不到合适的方法。 我仔细检查了一下,似乎 CM 想要调用 LocationDetailsViewModel 而不是 LocationViewModel 上的方法,即使每个选项卡项的关闭按钮中都存在类似的方法调用。

这是带有上下文菜单的代码:

<UserControl x:Class="RpgTools.LocationPresenter.Views.LocationView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:cal="http://www.caliburnproject.org"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:vm="clr-namespace:RpgTools.LocationPresenter.ViewModels"
             mc:Ignorable="d"
             d:DataContext="{d:DesignInstance Type=vm:LocationViewModel, IsDesignTimeCreatable=True}"
             cal:Bind.AtDesignTime="True"
             Padding="5">
<!-- Code left out for brevity -->
 <TabControl x:Name="Items"
                Grid.Column="2"
                Grid.Row="0"
                Margin="3,5,5,3"
                Visibility="{Binding Path=TabControlVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <StackPanel.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Close This"
                                      cal:Message.Attach="CloseTab($dataContext)">
                            </MenuItem>
                        </ContextMenu>
                    </StackPanel.ContextMenu>
                    <TextBlock Text="{Binding DisplayName}" />
                    <Button Padding="10,0,0,0"
                            Content="X"
                            Style="{DynamicResource NoChromeButton}"
                            cal:Message.Attach="CloseTab($dataContext)" />
                </StackPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>
    </TabControl>

【问题讨论】:

  • 你把它放在你想要的地方,然后你绑定到你需要绑定的地方。查看文档中的 Binding.ElementName。
  • 正如我已经写过的:把它放在 StackPanel 中是行不通的。该方法在子视图模型上执行并引发MethodNotFound 异常。
  • @Ruhrpottpatriot 您能否发布更多详细信息,说明当您将 XAML 附加到 StackPanel 时的外观以及数据类的外观?我最好的猜测是您没有在 ContextMenu 中正确设置 DataContext(使用 PlacementTarget 属性绑定),但我不确定是否是这种情况,因为我看不到您的代码
  • 您绑定到“[具有]执行事件的方法和属性的视图模型。”我没有说别的。我不知道那是谁或什么(您的问题在这方面不清楚),但您使用 Binding.ElementName 绑定到它。
  • 我用更多细节更新了我的问题。我希望这就足够了

标签: c# wpf mvvm data-binding caliburn.micro


【解决方案1】:

ContextMenus 不像其他控件那样是普通 VisualTree 的一部分,因此 .DataContext 不会像预期的那样被继承以用于绑定目的。

您需要将ContextMenu.DataContext 绑定到ContextMenu.PlacementTarget.DataContext,在本例中为StackPanel.DataContext

<ContextMenu DataContext="{Binding 
    RelativeSource={RelativeSource Self},
    Path=PlacementTarget.DataContext}">

【讨论】:

  • 不起作用我将您的代码添加到 ContextMenu,但我仍然遇到相同的异常。我的代码和你的完全一样。我什至试图重现它,但 IntelliSense 什么也没给我,编译器警告我他无法解析属性 DataContext
猜你喜欢
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多