WPF:如何在listview / gridview中控制上下文菜单的弹出窗口

时间:2017-02-12 08:11:55

标签: wpf listview gridview contextmenu

我有一个由两部分组成的问题,我希望可以同时问他们两个问题。

我有一个WPF ListView,其GridView视图。

前段时间我正在寻找一种在ContextMenu中设置ListView的方法,只有在用户右键单击ListView的实际项目时才会弹出。{/ p>

我在网上找到的所有解决方案都建议将ContextMenu放在ItemContainerStyle内,所以我这样做了,并且有效。

1。问题,一般的

但现在它让我思考......如果我的ListView包含数千个项目,这是否意味着我在内存中创建了数千个相同的ContextMenu?如果我这样做,是不是有更好的方法来获得一个项目ContextMenu

2。问题,具体问题已过时,请参阅下面的编辑

现在,当用户右键单击ContextMenu标头时,我会尝试弹出另一个GridView,并且所有解决方案都建议将其放入GridViewColumnHeader

我有两个问题。首先,它再次为每个列创建相同的ContextMenu,其次,当用户右键单击其中一个列标题时,只会弹出ContextMenu。如果标题区域内有可用空间(因为所有列都不需要所有可用空间),则右键单击标题区域的可用空间时会弹出ContextMenu

右键点击ContextMenu的标题区域时,有没有办法弹出一个 GridView

我希望解决方案只能在XAML中,如果可能的话。

感谢您的帮助。

修改

请忘记问题的第二部分。我发现ColumnHeaderContextMenu的{​​{1}}属性正是​​我正在寻找的东西。

2 个答案:

答案 0 :(得分:1)

假设以下自定义控件:

public class MTextBlock : TextBlock
{
    public MTextBlock ()
    {// breakpoint

    }
}
public class MContextMenu : ContextMenu
{
    public MContextMenu()
    {// breakpoint

    }
}

Xaml中的以下ItemsControl:

  <ItemsControl Name="ic" ItemTemplate="{StaticResource res}"/>

其中ItemsSource将在后面的代码中设置。

如果您使用以下设置

    <DataTemplate x:Key="res">
        <TextBlock Text="A a a a a ">
            <TextBlock.ContextMenu>
                <local:MContextMenu>
                    <MenuItem Header="Item1">
                        <local:MTextBlock Text="u" />
                    </MenuItem>
                </local:MContextMenu>
            </TextBlock.ContextMenu>
        </TextBlock> 
    </DataTemplate>

将生成 MContextMenu MTextBox 的多个实例。您可以通过在构造函数上设置断点来检查这一点。

但是,如果将控件声明为静态资源,例如:

<Window.Resources>
    <local:MContextMenu x:Key="cm">
        <MenuItem Header="Item1">
            <local:MTextBox Text="u" />
        </MenuItem>
    </local:MContextMenu>
    <DataTemplate x:Key="res">
        <TextBlock Text="{Binding Path=Name}" Background="Transparent" Width="100" ContextMenu="{StaticResource cm}"> 
        </TextBlock> 
    </DataTemplate>
</Window.Resources>

只会生成一个实例。再次通过设置正确的断点来检查它。请注意,在这种情况下,如果更改 MTextBox Text 属性,则会影响不同_ContextMenu_s中的所有_MTextBox_。

答案 1 :(得分:1)

  

如果我的ListView包含数千个项目,这是否意味着我在内存中创建了数千个相同的ContextMenus

没有

您可以通过创建自己的自定义ContextMenu类型,在其构造函数中设置断点并调试应用程序来确认:

Public Class MyContextMenu
    Inherits ContextMenu

    Public Sub New()
        Items.Add(New MenuItem() With {.Header = "1"})
        Items.Add(New MenuItem() With {.Header = "2"})
        Items.Add(New MenuItem() With {.Header = "3"})
    End Sub

End Class
<ListView x:Name="listView1">
    <ListView.Resources>
        <local:MyContextMenu x:Key="cm" />
    </ListView.Resources>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="ContextMenu" Value="{StaticResource cm}" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

对于您添加到Items ListView集合的每个项目,断点不会被点击一次,所以不要担心这一点。

使用StaticResource设置属性并不重要:

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Setter Property="ContextMenu">
            <Setter.Value>
                <local:MyContextMenu />
            </Setter.Value>
        </Setter>
    </Style>
</ListView.ItemContainerStyle>

设置ContextMenu的{​​{1}}属性是将上下文菜单与ItemContainerStyle容器相关联的正确方法。