2009-04-14 113 views
17

我有以下GridViewWPF:显示了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> 

现在我想上一个有界项目右键点击,让我来检索显示上下文菜单当我在后面的代码中处理事件时选择的项目。

以什么样的方式我可以做到这一点?


[更新]

Dennis Roche的代码,我现在有这样的:

<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.Control s.ContextMenu' 添加到'System.Object'类型的对象。 对象 错误'System.Windows.Controls.ContextMenu' 标记文件 'MusicRepo_Importer; component/controls/trackgridcontrol.xaml'。

什么问题?

+1

我能看到的第一个错误是您要设置两次ItemContainerStyle:首先是资源,然后是本地。 此外,上下文菜单需要是一个资源。这似乎是一个WPF的错误。我会用解决方案更新我的原始帖子。 – Dennis 2009-04-16 23:45:24

回答

19

是的,添加一个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> 

注意:您需要引用ContextMenu作为资源并且不能在本地定义它。

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

另请参阅我处理PreviewMouseLeftButtonDown事件,以便我可以确保项目聚焦(并且是当您查询ListView时当前选定的项目)。我发现当改变应用程序之间的焦点时,我不得不这样做,这可能不适用于你的情况。

更新

在代码隐藏文件,你需要的随身视觉树查找列表容器项目作为事件的原始源可以是该项目模板的元素(例如一个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这是使用我写的包装,快速走可视化树。子集发布在下面。

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); 
    } 
} 

我希望这些附加信息有帮助。

丹尼斯

+0

请参阅我发布的更新 – 2009-04-15 01:35:17

+1

非常感谢帮助队友。 – 2009-04-24 09:39:04

3

您可能会感兴趣的答案为this SO question - 我有同样的问题,但并不满足于使用MouseDown事件捕获被点击的项目。有几个人已经用简单易懂的方式回答了您可能感兴趣的解决方案。

摘要:您可以使用数据上下文将项目传递给处理程序或命令+命令参数设置。

8

丹尼斯,

爱的例子,但是我没有找到任何需要为您的视觉树助手......

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

然后MenuItem_Click事件我添加的代码看起来像这里面的:

private void menuItem_CopyUsername_Click(object sender, RoutedEventArgs e) 
{ 
    Clipboard.SetText(mySelectedItem.Username); 
} 

mySelectedItem是在ListView.SelectedItem使用

请勾选我是否有帮助...