2010-05-17 23 views
0

我一直試圖讓一個動態的ContextMenu顯示其collection of objects中的每個對象的名稱屬性。
這裏是一個具體的例子,我連接到webservicecontactsgroups一個特定的帳戶。所以我有那些作爲global variablesi display the contacts in a listboxi want to show on right click of a contact in the listbox the list of groups that it can be added to
能夠添加聯繫人到一個組我需要聯繫人(我有)的id和我在這裏尋找的組的id是我的代碼。如何使用MenuItem.ItemContainerStyle時傳遞數據

xmlns:serviceAdmin="clr-namespace:MyWpfApp.serviceAdmin" 
...... 
<ListBox.ContextMenu> 
         <ContextMenu> 
          <MenuItem Header="Refresh" Click="RefreshContact_Click"></MenuItem> 
          <MenuItem Header="Add New Contact" Click="ContactNew_Click"></MenuItem> 
          <MenuItem Header="Add to Group" Name="groupMenus"> 
           //<!--<MenuItem.Resources> 
            // <DataTemplate DataType="{x:Type serviceAdmin:groupInfo}" x:Key="groupMenuKey" > 
            // <MenuItem> 
            //  <TextBlock Text="{Binding name}" /> 
            // </MenuItem> 
            // </DataTemplate> 

           // </MenuItem.Resources>--> 
           <MenuItem.ItemContainerStyle> 
            <Style> 
             <Setter Property="MenuItem.Header" Value="{Binding name}"/> 
             <Setter Property="MenuItem.Tag" Value="{Binding id}" /> 

            </Style> 
           </MenuItem.ItemContainerStyle> 
          </MenuItem> 
          <MenuItem Header="Delete Selected" Click="ContactDelete_Click"></MenuItem> 
         </ContextMenu> 
        </ListBox.ContextMenu> 
        ...... 

和xaml.cs

//this code is in the method that loads the groups 
loadedgroup = service.getGroups(session.key, null); 
groupListBox.ItemsSource = loadedgroup; 
groupMenus.ItemsSource = loadedgroup.ToList(); 

這段代碼顯示了羣體好嗎的名字,但我需要的組ID點擊。
如果你已經注意到我評論了一部分xaml代碼。有,我可以綁定(輕鬆)的ID給tag.But它不會工作和MenuItem.ItemContainerStyle是一個工作,但隨後我迷路了:

問題1:如何創建對於具有組的名稱的子菜單的點擊事件的處理方法?
問題2:我如何獲得點擊的組ID以使用?

感謝您的閱讀並善意幫助我在此

回答

2

下面是一個使用數據綁定的示例。子菜單項的數據上下文是Group的一個實例。

XAML:

<Window x:Class="MenuTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="300" Width="300"> 
    <Grid Background="Red"> 
     <Grid.ContextMenu> 
      <ContextMenu> 
       <MenuItem Header="Menu Item 1"></MenuItem> 
       <MenuItem Header="Menu Item 2"></MenuItem> 
       <MenuItem Header="SubMenu" ItemsSource="{Binding Path=Groups}" 
          Click="OnGroupMenuItemClick"> 
        <MenuItem.ItemTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding Path=Name}" /> 
         </DataTemplate> 
        </MenuItem.ItemTemplate> 
       </MenuItem> 
      </ContextMenu> 
     </Grid.ContextMenu> 
    </Grid> 
</Window> 

後面的代碼:

using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 

namespace MenuTest 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      Groups = new List<Group>(); 
      Groups.Add(new Group() { Name = "Group1", Id = 1 }); 
      Groups.Add(new Group() { Name = "Group2", Id = 2 }); 
      Groups.Add(new Group() { Name = "Group3", Id = 3 }); 

      DataContext = this; 
     } 

     public List<Group> Groups { get; set; } 

     private void OnGroupMenuItemClick(object sender, RoutedEventArgs e) 
     { 
      MenuItem menuItem = e.OriginalSource as MenuItem; 
      Group group = menuItem.DataContext as Group; 
     } 
    } 

    public class Group 
    { 
     public string Name { get; set;} 
     public int Id { get; set;} 
    } 
} 
+0

感謝的作品 – 2010-05-17 15:31:22

0

你可以做到這一點不使用Click事件,或任何令人費解的。

麻煩的是,你的命令有一個DataContext的(視圖模型)和項目有另一個。因此,有兩種選擇:要麼把命令上的項目中的ItemsSource(更靈活,因爲他們可以有不同的命令),或做的RelativeSource綁定備份到視圖,通過view.DataContext搶視圖模型,並從得到的命令那。這爲您節省了一些簡單的麻煩,將命令傳遞給所有這些數據項。

注意,因爲我們通過一個樣式這樣做,我們會在同一個命令綁定到每個菜單項,如果我們從一些的DataContext這是通用於所有的樣式相似的菜單項獲得命令。但是由於我們是從類似數據項目列表中自己生成項目的,這可能就是您想要的。如果不是,則將命令放在數據項上。

如果您的ItemsSource中的項目有命令,那麼該數據項的公有屬性可以很容易地綁定到您的ItemContainerStyle中的MenuItem.Command。更多的C#,更少的XAML。

這樣做還有一個好處,就是在一個更大的菜單系統中只有一個本地化的子菜單上工作得很好,其他菜單項以常規方式定義。這是部分MRU清單實施。您可以非常輕鬆地爲其他類似的子菜單執行相同的操作,或者只需很少的工作就可以完成整個主菜單樹。

爲簡單起見,我假設項目有一個名稱空間,在XAML中定義爲local,並且此XAML位於名爲MainWindow的視圖中。

這兩個都已經在一個完整的實現中進行了測試,但是下面的內容並不完整:爲了便於管理,所以將它簡化爲使XAML有意義的最小值。我最終使用了RelativeSource AncestorType版本,因爲它更簡單一些,我不需要給列表項列出不同的命令,但是我保留了其他版本的註釋。

<Window.Resources> 
    <!-- ... --> 
    <DataTemplate DataType="{x:Type local:MRUListItem}" > 
     <Label Content="{Binding HeaderText}" /> 
    </DataTemplate> 
    <!-- ... --> 
</Window.Resources> 

<!-- ... --> 

<Menu> 
    <MenuItem Header="_File"> 
     <MenuItem Header="_Save File" 
        Command="{Binding SaveFileCommand}" /> 

     <!-- ... --> 
     <!-- etc. --> 
     <!-- ... --> 

     <MenuItem Header="_Recent Files" 
        ItemsSource="{Binding MRUList}"> 
      <MenuItem.ItemContainerStyle> 
       <Style TargetType="MenuItem"> 
        <Setter Property="Command" 
          Value="{Binding FileOpenCommand}" /> 
        <Setter Property="CommandParameter" 
          Value="{Binding FileName}" /> 
       </Style> 
      </MenuItem.ItemContainerStyle> 
     </MenuItem> 

     <!-- etc. --> 
    </MenuItem> 

    <!-- ... --> 
</Menu> 

替代的RelativeSource版本,得到了命令直接從視圖模型在XAML:

<!-- 
      <MenuItem.ItemContainerStyle> 
       <Style TargetType="MenuItem"> 
        <Setter Property="Command" 
         Value="{Binding RelativeSource={RelativeSource 
         AncestorType={x:Type local:MainWindow}}, 
         Path=DataContext.MRUFileOpenCommand}" /> 
        <Setter Property="CommandParameter" 
         Value="{Binding FileName}" /> 
       </Style> 
      </MenuItem.ItemContainerStyle> 
--> 

C#

public class MRUList : ObservableCollection<MRUListItem> 
{ 
    // The owning ViewModel provides us with his FileOpenCommand 
    // initially. 
    public MRUList(ICommand fileOpenCommand) 
    { 
     FileOpenCommand = fileOpenCommand; 
     CollectionChanged += CollectionChangedHandler; 
    } 

    public ICommand FileOpenCommand { get; protected set; } 

    // Methods to renumber and prune when items are added, 
    // remove duplicates when existing item is re-added, 
    // and to assign FileOpenCommand to each new MRUListItem. 

    // etc. etc. etc. 
} 

public class MRUListItem : INotifyPropertyChanged 
{ 
    public ICommand FileOpenCommand { get; set; } 

    private int _number; 
    public int Number { 
     get { return _number; } 
     set 
     { 
      _number = value; 
      OnPropertyChanged("Number"); 
      OnPropertyChanged("HeaderText"); 
     } 
    } 
    public String HeaderText { 
     get { 
      return String.Format("_{0} {1}", Number, FileName); 
     } 
    } 

    // etc. etc. etc. 
} 
相關問題