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

22

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

必须执行什么操作才能允许在运行时动态添加菜单项到菜单中?

注意:以下代码无法正常工作。

            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文件中定义。我想在该菜单及其现有菜单项上添加其他菜单项。但正如上面所述,以上代码并没有起到任何作用。

5个回答

28
//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);

这对我不起作用,而且与我尝试的相同。我错过了什么吗?请查看不起作用的示例文本。 - Jon Ediger
我刚刚添加了一个新菜单,并使用默认控件属性运行代码,结果如预期。我尝试了你的代码,在我的机器上也能正常工作。创建一个新项目,添加一个基本菜单,不要调整任何属性,再次尝试你的代码。 - Whytespot
6
关键似乎是不要预先定义任何菜单项。当我预先定义它们时,就无法动态添加它们;但是如果我不预先定义它们,我就可以添加它们。 - Jon Ediger
1
在这行代码上出现错误,显示为“无法将类型为'System.String'的对象转换为类型'System.Windows.Controls.MenuItem'。”: MenuItem newExistMenuItem = (MenuItem)this.MainMenu.Items[0]; - Uzair Ali
点击事件怎么样? - Hrvoje Batrnek

11

我已成功地向预定义的菜单项添加了菜单项。 在下面的代码中,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
}

1
点击事件未被调用。 - Hrvoje Batrnek

6

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

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

很糟糕

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

是好的


0

我必须为我打算动态创建子项的现有项目提供名称。此外,我遇到了一个问题,我正在利用Window_Loaded事件,但在运行以下内容后它跳出了该事件:

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

在运行上述代码行之前,我必须确保加载了菜单项。

这个问题常见的原因是因为智能感知推断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);
            }

-2

ASP.NET -> WEB Forms -> 创建菜单

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

3
你为什么觉得需要在这里介绍SQL呢? - Lee Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接