WPF:如何在运行时将新菜单项添加到菜单中?

问题描述:

我有一个简单的WPF应用程序和一个菜单。我需要在运行时动态添加菜单项。当我简单地创建一个新的菜单项并将其添加到其父项MenuItem中时,无论是否调用UpdateLayout,它都不会显示在菜单中。WPF:如何在运行时将新菜单项添加到菜单中?

允许菜单在运行时动态添加其他项目时会发生什么?

注意:以下代码不起作用。

  MenuItem mi = new MenuItem(); 
      mi.Header = "Item to add"; 
      mi.Visibility = Visibility.Visible; 
      //addTest is a menuitem that exists in the forms defined menu 
      addTest.Items.Add(mi); 
      addTest.UpdateLayout(); 

目前,默认的菜单项是在xaml文件中定义的。我想添加额外的菜单项到这个菜单和它现有的菜单项。但是,如上所述,上面的代码什么都不做。

//Add to main menu 
MenuItem newMenuItem1 = new MenuItem(); 
newMenuItem1.Header = "Test 123"; 
this.MainMenu.Items.Add(newMenuItem1); 

//Add to a sub item 
MenuItem newMenuItem2 = new MenuItem(); 
MenuItem newExistMenuItem = (MenuItem)this.MainMenu.Items[0]; 
newMenuItem2.Header = "Test 456"; 
newExistMenuItem.Items.Add(newMenuItem2); 
+0

这不适合我,反映了我已经尝试过。我错过了什么?请参阅不起作用的示例文本。 – 2008-11-14 22:05:57

+0

我刚刚添加了一个新菜单,并运行了默认控件属性的代码,并按预期工作。我试过你的代码,它在我的机器上工作。创建一个新项目,添加一个基本菜单并且不要调整它的任何属性并再次尝试你的代码。 – Whytespot 2008-11-14 22:14:16

我已成功将菜单项添加到预定义的菜单项。 在以下代码中,LanguageMenu是在xaml的设计视图中定义的,然后在C#中添加了子项。

XAML:

<MenuItem Name="LanguageMenu" Header="_Language"> 
    <MenuItem Header="English" IsCheckable="True" Click="File_Language_Click"/> 
</MenuItem> 

C#:

// Clear the existing item(s) (this will actually remove the "English" element defined in XAML) 
LanguageMenu.Items.Clear(); 

// Dynamically get flag images from a specified folder to use for definingthe menu items 
string[] files = Directory.GetFiles(Settings.LanguagePath, "*.png"); 
foreach (string imagePath in files) 
{ 
    // Create the new menu item 
    MenuItem item = new MenuItem(); 

    // Set the text of the menu item to the name of the file (removing the path and extention) 
    item.Header = imagePath.Replace(Settings.LanguagePath, "").Replace(".png", "").Trim("\\".ToCharArray()); 
    if (File.Exists(imagePath)) 
    { 
    // Create image element to set as icon on the menu element 
    Image icon = new Image(); 
    BitmapImage bmImage = new BitmapImage(); 
    bmImage.BeginInit(); 
    bmImage.UriSource = new Uri(imagePath, UriKind.Absolute); 
    bmImage.EndInit(); 
    icon.Source = bmImage; 
    icon.MaxWidth = 25; 
    item.Icon = icon; 
    } 

    // Hook up the event handler (in this case the method File_Language_Click handles all these menu items) 
    item.Click += new RoutedEventHandler(File_Language_Click); 

    // Add menu item as child to pre-defined menu item 
    LanguageMenu.Items.Add(item); // Add menu item as child to pre-defined menu item 
} 

我知道这是一个老的文章,但我遇到了同样的问题。在我的情况下,问题是在XAML中,<menuitem>直接包含在<toolbar>中。一旦我将<menuitem>放入<menu>之内,它就开始工作。所以:

<toolbar> 
    <menuitem> 
    </menuitem> 
</toolbar> 

不好

<toolbar> 
    <menu> 
     <menuitem> 
     </menuitem> 
    </menu> 
</toolbar> 

ASP.NET - > Web窗体 - >创建菜单

CREATE TABLE `webmenu` (
    `idmenu` smallint(5) NOT NULL, 
    `submenu` smallint(5) DEFAULT NULL, 
    `menu_title` varchar(45) DEFAULT NULL, 
    `menu_url` varchar(45) DEFAULT NULL, 
    `status` enum('1','0') DEFAULT '1', 
    PRIMARY KEY (`idmenu`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

SELECT 
idmenu, 
(select menu_title from webmenu where idmenu=wm.submenu and status='1') as childmenu, 
menu_title, 
menu_url 
FROM tartyp.webmenu as wm 
where 
status='1' 
order by idmenu, submenu; 

 cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn); 

     reader = cmd.ExecuteReader(); 
     MainMenu.Items.Clear(); 
     while (reader.Read()) 
     { 

      if (reader["childmenu"] == DBNull.Value) 
      { 
       MenuItem homeMenuItem = new MenuItem(reader["menu_title"].ToString(), reader["menu_url"].ToString()); 
       MainMenu.Items.Add(homeMenuItem); 
      } 
      else 
      { 
       String childmenu = reader["childmenu"].ToString();      

       for (int i = 0; i < MainMenu.Items.Count; i++) 
       { 
        if (MainMenu.Items[i].Text == childmenu) 
        {              
         MenuItem childMenuItem = new MenuItem(reader["menu_title"].ToString(), reader["menu_url"].ToString()); 
         MenuItem findMenuItem = MainMenu.Items[i]; 
         findMenuItem.ChildItems.Add(childMenuItem); 
         break;  
        } 
       } 
      } 

     } 
     reader.Close(); 
     conn.Close(); 

我必须为我打算动态创建子项目的现有项目提供名称。此外,我遇到了我在那里窃听到Window_Loaded事件的问题,它运行在这之后跳出事件:

row.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 

我必须确保我上面跑前行加载的菜单项。

这个问题可能很常见的原因是因为intellisense推断Items集合是“只读”的。这个答案是部分补充的,因为上面的答案似乎表明,如果你有先前存在的项目,你必须在代码中删除它们或者根本没有它们。这是不正确的。我已经能够得到这与预先存在的项目,并在代码中添加额外的动态菜单项的工作:

<DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch" Margin="12,29,12,12" Name="grid" VerticalAlignment="Stretch" Background="#FF3A81A0" AlternatingRowBackground="#FFD9EEF2" FontSize="15" RowHeaderWidth="0" KeyDown="grid_KeyDown"> 
     <DataGrid.ContextMenu> 
      <ContextMenu> 
       <MenuItem Header="_Encrypt Row Values" Click="MenuItem_ContextMenu_Click_EncryptRowValues" Name="MenuItem_EncryptRowValues" /> 
       <MenuItem Header="De_crypt Row Values" Click="MenuItem_ContextMenu_Click_DecryptRowValues" Name="MenuItem_DecryptRowValues" /> 
       <MenuItem Header="Copy Row_s" Click="MenuItem_ContextMenu_Click_CopyRows" /> 
      </ContextMenu> 
     </DataGrid.ContextMenu> 
     <DataGrid.Resources> 


      //Add Encryption Menu Items 
      for (int i=0; i< encryptionKeys.Count; i++) 
      { 
       MenuItem keyOption = new MenuItem(); 
       keyOption.Header = "_" + i.ToString() + " " + encryptionKeys[i]; 
       MenuItem_EncryptRowValues.Items.Add(keyOption); 
      } 

      //Add Decryption Menu Items 
      for (int i = 0; i < encryptionKeys.Count; i++) 
      { 
       MenuItem keyOption = new MenuItem(); 
       keyOption.Header = "_" + i.ToString() + " " + encryptionKeys[i]; 
       MenuItem_DecryptRowValues.Items.Add(keyOption); 
      }