C# WPF:显示GridView的关联菜单';s项目

C# WPF:显示GridView的关联菜单';s项目,c#,wpf,xaml,contextmenu,C#,Wpf,Xaml,Contextmenu,我有以下GridView: <ListView Name="TrackListView" ItemContainerStyle="{StaticResource itemstyle}"> <ListView.View> <GridView> <GridViewColumn Header="Title" Width="100" HeaderTemplate="{StaticResource BlueHeade

我有以下
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>

现在,我想在右键单击一个有界项时显示一个上下文菜单,它允许我在代码隐藏中处理事件时检索所选的项

我可以用什么可能的方式来实现这一点


[更新]

下面是代码,我现在有了这个:

    <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>

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

无法添加类型为的内容 “System.Windows.Controls.ContextMenu” 指向“System.object”类型的对象。 对象错误 “System.Windows.Controls.ContextMenu” 在标记文件中 “MusicRepo_进口商;组件/controls/trackgridcontrol.xaml'


有什么问题吗?

是的,使用关联菜单添加ListView.ItemContainerStyle

<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>
MyVisualTreeHelper的
MyVisualTreeHelper
使用我编写的包装器快速遍历可视化树。下面是一个子集

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);
  }
}
公共静态类MyVisualTreeHelper
{
静态bool-AlwaysTrue(T-obj){返回真;}
/// 
///在可视树上查找给定项的父项。如果该元素是ContentElement或FrameworkElement
///它将使用逻辑树来跳转间隙。
///如果找不到匹配项,则返回空引用。
/// 
///要查找的元素的类型
///所需物品的直接或间接子项。
///与提交的类型参数匹配的第一个父项。如果找不到匹配的项,则返回空引用。
公共静态T FindParent(DependencyObject子对象),其中T:DependencyObject
{
返回FindParent(子女,始终为父母);
}
公共静态T FindParent(DependencyObject子级,谓词谓词),其中T:DependencyObject
{
DependencyObject父对象=GetParent(子对象);
如果(父项==null)
返回null;
//检查父项是否与我们要查找的类型和谓词匹配
if((父项是T)和&(谓词((T)父项)))
将父对象返回为T;
其他的
返回FindParent(父级);
}
静态DependencyObject GetParent(DependencyObject子对象)
{
DependencyObject父对象=null;
if(子对象是可视的| |子对象是可视的3D)
父级=VisualTreeHelper.GetParent(子级);
//如果无法通过可视树找到父级,请尝试使用逻辑树。
返回父级??LogicalTreeHelper.GetParent(子级);
}
}
我希望这些补充信息能有所帮助


Dennis

您可能对的答案感兴趣-我有相同的问题,但不满意使用mousedown事件捕获单击的项目。一些人给出了您可能感兴趣的简单易懂的解决方案

小结:您可以使用数据上下文将项目传递给处理程序,或使用command+command参数设置。

Dennis

喜欢这个例子,但是我没有发现任何需要你的可视化树助手

   <ListView.Resources>
    <ContextMenu x:Key="ItemContextMenu">
        <MenuItem x:Name="menuItem_CopyUsername"
                  Click="menuItem_CopyUsername_Click"
                  Header="Copy Username">
            <MenuItem.Icon>
                <Image Source="/mypgm;component/Images/Copy.png" />
            </MenuItem.Icon>
        </MenuItem>
        <MenuItem x:Name="menuItem_CopyPassword"
                  Click="menuItem_CopyPassword_Click"
                  Header="Copy Password">
            <MenuItem.Icon>
                <Image Source="/mypgm;component/Images/addclip.png" />
            </MenuItem.Icon>
        </MenuItem>
        <Separator />
        <MenuItem x:Name="menuItem_DeleteCreds"
                  Click="menuItem_DeleteCreds_Click"
                  Header="Delete">
            <MenuItem.Icon>
                <Image Source="/mypgm;component/Images/Delete.png" />
            </MenuItem.Icon>
        </MenuItem>
    </ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
    </Style>
</ListView.ItemContainerStyle>
mySelectedItem用于ListView。SelectedItem:

 <ListView x:Name="ListViewCreds" SelectedItem="{Binding mySelectedItem, UpdateSourceTrigger=PropertyChanged}" ....

我看到的第一个错误是,您将ItemContainerStyle设置了两次:首先设置为资源,然后在本地设置。此外,上下文菜单需要是一个资源。这似乎是WPF的一个bug。我将用一个解决方案更新我的原始帖子。你能详细说明在PreviewMouseLeftButtonDown上需要做什么吗?我已经用代码隐藏中发生的事情的细节更新了答案。任何试图实现这一点的人,都可以使用System.Windows.Media;使用System.Windows.Media.Media3D;
private void menuItem_CopyUsername_Click(object sender, RoutedEventArgs e)
{
    Clipboard.SetText(mySelectedItem.Username);
}
 <ListView x:Name="ListViewCreds" SelectedItem="{Binding mySelectedItem, UpdateSourceTrigger=PropertyChanged}" ....