WPF:显示一个上下文菜单,GridView的项目 [英] WPF: Displaying a Context Menu for a GridView's Items

查看:438
本文介绍了WPF:显示一个上下文菜单,GridView的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有如下的 GridView控件

<ListView Name="TrackListView" ItemContainerStyle="{StaticResource itemstyle}">
    <ListView.View>
    	<GridView>
			<GridViewColumn Header="Title" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Name}"/>
			<GridViewColumn Header="Artist" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Album.Artist.Name}" />
			<GridViewColumn Header="Album" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Album.Name}"/>
			<GridViewColumn Header="Length" Width="100" HeaderTemplate="{StaticResource BlueHeader}"/>
		</GridView>
	 </ListView.View>
</ListView>

现在我想上一个有界项目右击,让我当我在code处理该事件背后检索选定的项目显示上下文菜单。

Now I would like to display a context menu on a right click on a bounded item that will allow me to retrieve the item selected when I handle the event in the code behind.

在什么可能的方式,我可以做到这一点?

In what possible way can I accomplish this?


[更新]

随着<一个href=\"http://stackoverflow.com/questions/747872/wpf-displaying-a-context-menu-for-a-gridviews-items/749671#749671\">Dennis的罗氏 code,我现在有这样的:

Following Dennis Roche's code, I now have this:

    <ListView Name="TrackListView" ItemContainerStyle="{StaticResource itemstyle}">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnListViewItem_PreviewMouseLeftButtonDown" />
                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <MenuItem Header="Add to Playlist"></MenuItem>
                        </ContextMenu>
                     </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>

        <ListView.View>
            <GridView>
                <GridViewColumn Header="Title" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Name}"/>
                <GridViewColumn Header="Artist" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Album.Artist.Name}" />
                <GridViewColumn Header="Album" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Album.Name}"/>
                <GridViewColumn Header="Length" Width="100" HeaderTemplate="{StaticResource BlueHeader}"/>
            </GridView>
         </ListView.View>
    </ListView>

但在运行时,我收到此异常:

But upon running, I am receiving this exception:

无法添加类型的内容
  System.Windows.Controls.ContextMenu
  以类型的对象System.Object的。
  错误在对象
  System.Windows.Controls.ContextMenu
  在标记文件
  'MusicRepo_Importer;组件/控制/ trackgridcontrol.xaml

Cannot add content of type 'System.Windows.Controls.ContextMenu' to an object of type 'System.Object'. Error at object 'System.Windows.Controls.ContextMenu' in markup file 'MusicRepo_Importer;component/controls/trackgridcontrol.xaml'.

这是什么问题?

推荐答案

是,添加一个ListView.ItemContainerStyle通过上下文菜单。

Yes, add a ListView.ItemContainerStyle with the Context Menu.

<ListView>
  <ListView.Resources>
    <ContextMenu x:Key="ItemContextMenu">
      ...
    </ContextMenu>
  </ListView.Resources>
  <ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
      <EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnListViewItem_PreviewMouseLeftButtonDown" />
      <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}"/>
    </Style>
  </ListView.ItemContainerStyle>
</ListView>

注:您需要引用文本菜单作为一种资源,不能在本地定义它。

NOTE: You need to reference the ContextMenu as a resource and cannot define it locally.

这将使整个行的上下文菜单。 :)

This will enable the context menu for the entire row. :)

另请参阅我处理 previewMouseLeftButtonDown 事件,所以我可以确保该项目的重点是(而且是当前选定的项目,当您查询的ListView)。我发现我改变应用程序之间的焦点时,这可能不是你的情况真有这一点。

Also see that I handle the PreviewMouseLeftButtonDown event so I can ensure the item is focused (and is the currently selected item when you query the ListView). I found that I had to this when changing focus between applications, this may not be true in your case.

更新

在隐藏文件code你需要步行式可视化树找到列表容器项作为事件的原始源可以是该项目模板的元件(例如一个StackPanel中)。

In the code behind file you need to walk-up the visual tree to find the list container item as the original source of the event can be an element of the item template (e.g. a stackpanel).

void OnListViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  if (e.Handled)
    return;

  ListViewItem item = MyVisualTreeHelper.FindParent<ListViewItem>((DependencyObject)e.OriginalSource);
  if (item == null)
    return;

  if (item.Focusable && !item.IsFocused)
    item.Focus();
}

MyVisualTreeHelper 这是使用我已经写了快速走可视化树的包装。一个子集贴在下面。

The MyVisualTreeHelper that is use a wrapper that I've written to quickly walk the visual tree. A subset is posted below.

public static class MyVisualTreeHelper
{
  static bool AlwaysTrue<T>(T obj) { return true; }

  /// <summary>
  /// Finds a parent of a given item on the visual tree. If the element is a ContentElement or FrameworkElement 
  /// it will use the logical tree to jump the gap.
  /// If not matching item can be found, a null reference is returned.
  /// </summary>
  /// <typeparam name="T">The type of the element to be found</typeparam>
  /// <param name="child">A direct or indirect child of the wanted item.</param>
  /// <returns>The first parent item that matches the submitted type parameter. If not matching item can be found, a null reference is returned.</returns>
  public static T FindParent<T>(DependencyObject child) where T : DependencyObject
  {
    return FindParent<T>(child, AlwaysTrue<T>);
  }

  public static T FindParent<T>(DependencyObject child, Predicate<T> predicate) where T : DependencyObject
  {
    DependencyObject parent = GetParent(child);
    if (parent == null)
      return null;

    // check if the parent matches the type and predicate we're looking for
    if ((parent is T) && (predicate((T)parent)))
      return parent as T;
    else
      return FindParent<T>(parent);
  }

  static DependencyObject GetParent(DependencyObject child)
  {
    DependencyObject parent = null;
    if (child is Visual || child is Visual3D)
      parent = VisualTreeHelper.GetParent(child);

    // if fails to find a parent via the visual tree, try to logical tree.
    return parent ?? LogicalTreeHelper.GetParent(child);
  }
}

我希望这些额外的信息帮助。

I hope this additional information helps.

丹尼斯

这篇关于WPF:显示一个上下文菜单,GridView的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆