C# WPF:如何在运行时向菜单添加新菜单项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/291522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF: How can you add a new menuitem to a menu at runtime?
提问by Jon Ediger
I have a simple WPF application with a menu. I need to add menu items dynamically at runtime. When I simply create a new menu item, and add it onto its parent MenuItem, it does not display in the menu, regardless of if UpdateLayout is called.
我有一个带有菜单的简单 WPF 应用程序。我需要在运行时动态添加菜单项。当我简单地创建一个新菜单项并将其添加到其父 MenuItem 时,无论是否调用 UpdateLayout,它都不会显示在菜单中。
What must happen to allow a menu to have additional items dynamically added at runtime?
允许菜单在运行时动态添加其他项目必须发生什么?
Note: the following code doesn't work.
注意:以下代码不起作用。
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();
At the moment, the default menu items are defined in the xaml file. I want to add additional menu items onto this menu and its existing menu items. However, as stated, the above code does nothing.
目前,默认菜单项在 xaml 文件中定义。我想在此菜单及其现有菜单项上添加其他菜单项。但是,如上所述,上面的代码什么也不做。
采纳答案by Whytespot
//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);
回答by awe
I have successfully added menu items to a pre-defined menu item. In the following code, the LanguageMenu is defined in design view in th xaml, and then added the sub items in C#.
我已成功将菜单项添加到预定义的菜单项中。在下面的代码中,LanguageMenu 在 thxaml 的设计视图中定义,然后在 C# 中添加子项。
XAML:
XAML:
<MenuItem Name="LanguageMenu" Header="_Language">
<MenuItem Header="English" IsCheckable="True" Click="File_Language_Click"/>
</MenuItem>
C#:
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
}
回答by Patrick Hendry
I ran into the same problem. In my case the problem was that in the XAML the <menuitem>
was directly contained in a <toolbar>
. Once I put the <menuitem>
inside a <menu>
it started working. So:
我遇到了同样的问题。在我的情况下,问题是在 XAML<menuitem>
中直接包含在<toolbar>
. 一旦我把<menuitem>
里面一个<menu>
它开始工作。所以:
<toolbar>
<menuitem>
</menuitem>
</toolbar>
is bad
不好
<toolbar>
<menu>
<menuitem>
</menuitem>
</menu>
</toolbar>
is good
很好
回答by Коныч Казах
ASP.NET -> WEB Forms -> Create Menu
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();
回答by Brandon Hawbaker
I did have to provide names for the existing items I intended to dynamically create sub-items for. In addition, I ran into an issue where I was tapping into the Window_Loaded event and it was jumping out of the event after running this:
我确实必须为我打算为其动态创建子项目的现有项目提供名称。此外,我遇到了一个问题,我正在使用 Window_Loaded 事件,并且在运行此事件后它跳出事件:
row.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
I had to ensure I loaded the menu items before running the line above.
我必须确保在运行上面的行之前加载了菜单项。
The reason this question is likely common is because intellisense infers that the Items collection is "Read-Only". This answer is partially supplemental because the answers above seem to indicate that if you have preexisting items you either have to remove them in code or not have them at all. This isn't true. I have been able to get this working with preexisting items and adding additional dynamic menu items in code:
这个问题可能很常见的原因是因为智能感知推断 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);
}