【问题标题】:ContextMenu for ListViewItem only仅适用于 ListViewItem 的 ContextMenu
【发布时间】:2013-09-26 02:27:47
【问题描述】:

我有一个上下文菜单 - 问题是我需要它仅在单击 listviewitem 时打开。现在,如果我单击列表视图或标题中的任意位置,它将打开。

<ListView> 
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem Header="More Info" Command="{Binding MoreInfo}" />
        </ContextMenu>
     </ListView.ContextMenu>
     <ListView.View> 
         <GridView> 
           <!-- columns and stuff here -->
         </GridView>
     </ListView.View>
 </ListView>

我已尝试将 ContextMenu 添加为资源并将其应用为样式,但这会破坏命令(单击更多信息应打开一个对话框窗口,这种方式不起作用)

<ListView.Resources>
    <ContextMenu x:Key="ItemContextMenu">
        <MenuItem Header="More Info" Command="{Binding MoreInfo}" Background="WhiteSmoke" />
    </ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}" >
        <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
    </Style>
</ListView.ItemContainerStyle>

所以不确定如何将上下文菜单限制为仅 listviewitem 并让命令起作用。

【问题讨论】:

    标签: c# wpf contextmenu listviewitem


    【解决方案1】:

    在模板的命令绑定中使用RelativeSource,就可以了:

    <ListView.Resources>
        <ContextMenu x:Key="ItemContextMenu">
            <MenuItem Header="More Info" Command="{Binding Path=DataContext.MoreInfo, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Background="WhiteSmoke" />
        </ContextMenu>
    </ListView.Resources>
    
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}" >
            <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
        </Style>
    </ListView.ItemContainerStyle>
    

    【讨论】:

    • 谢谢,这行得通。您可以准确解释这是在做什么的任何更改?我对 FindAncestor 做了什么有点模糊。
    • 在您的情况下,RelativeSource 试图在 UI 树中找到第一个 ListView 控件并将其用作绑定源。因此,我们必须写DataContext,然后是属性名。
    【解决方案2】:

    扩展这篇非常有用的帖子...如果您的ContextMenuControlTemplate 中有自定义按钮或其他对象,我将上面的答案与Closing ContextMenu with Templated MenuItems 的答案结合起来,这样当用户点击ButtonContextMenu 仅使用 XAML 正常关闭。这花了大约 10 个小时才完成。希望它可以节省您的时间。支持 MVVM ICommand 使用。我还使用了 [this post][2] 中的 StyleContextMenu,以消除 90 年代的外观。

    <ListView.Resources>
        <ContextMenu x:Key="ItemContextMenu" Style="{StaticResource HorizontalContextMenu}">
            <MenuItem>
                <MenuItem.Template>
                    <ControlTemplate>
                        <Grid MinHeight="50" MinWidth="50">
                            <Button Style="{StaticResource CloseAppButton}" Command="{Binding Path=DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" >
                                <Button.Triggers>
                                    <EventTrigger RoutedEvent="Button.Click">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContextMenu.IsOpen)" Storyboard.Target="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}">
                                                    <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <sys:Boolean>False</sys:Boolean>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </Button.Triggers>
                            </Button>
                        </Grid>
                    </ControlTemplate>
                </MenuItem.Template>
            </MenuItem>
    
            <MenuItem>
                <MenuItem.Template>
                    <ControlTemplate>
                        <Grid MinHeight="50" MinWidth="50">
                            <Button Style="{StaticResource AddButton}" Command="{Binding Path=DataContext.TestCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" >
                                <Button.Triggers>
                                    <EventTrigger RoutedEvent="Button.Click">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContextMenu.IsOpen)" Storyboard.Target="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}">
                                                    <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <sys:Boolean>False</sys:Boolean>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </Button.Triggers>
                            </Button>
                        </Grid>
                    </ControlTemplate>
                </MenuItem.Template>
            </MenuItem>
    
            <MenuItem>
                <MenuItem.Template>
                    <ControlTemplate>
                        <Grid MinHeight="50" MinWidth="50">
                            <Button Style="{StaticResource PluginInfoButton}" Command="{Binding Path=DataContext.TestCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" >
                                <Button.Triggers>
                                    <EventTrigger RoutedEvent="Button.Click">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContextMenu.IsOpen)" Storyboard.Target="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}}">
                                                    <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <sys:Boolean>False</sys:Boolean>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </Button.Triggers>
                            </Button>
                        </Grid>
                    </ControlTemplate>
                </MenuItem.Template>
            </MenuItem>
        </ContextMenu>
    
    </ListView.Resources>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}" >
            <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </ListView.ItemContainerStyle>
    

    【讨论】:

      猜你喜欢
      • 2014-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-23
      • 1970-01-01
      • 2020-07-12
      • 1970-01-01
      相关资源
      最近更新 更多