2009-04-14 104 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使用

請勾選我是否有幫助...