这是我得到的结果
foreach (var menuItem in oMenuItemList)
{
var cContextMenuItem = menuItem as MenuItem;
if (cContextMenuItem != null)
{
_oContextMenu.Items.Add(menuItem);
if (cContextMenuItem.Header.ToString() == "1.1")
{
MenuItem newMenuItem2 = new MenuItem();
MenuItem newExistMenuItem = (MenuItem)this._oContextMenu.Items[0];
newExistMenuItem.Items.Add(newMenuItem2);
_oContextMenu.Items.Add(newExistMenuItem);
}
}
}
_oContextMenu.ItemsSource = oMenuItemList;
更新代码
IEnumerable oMenuItemList = null;
oMenuItemList = GetContextMenuItems(sMenuItems);
//the function
private List<object> GetContextMenuItems(string sMenuItems)
{
//returns the list
}
_oContextMenu.ItemsSource = oMenuItemList;
在此之后,我试图操纵 _oContextMenu。
最佳答案
这是您的确切图像的示例:
Xaml:
<ContextMenu Opened="ContextMenu_OnOpened">
<MenuItem Header="1.0" />
<MenuItem Header="1.1" />
<MenuItem Header="1.2" />
<MenuItem Header="2.0" />
<MenuItem Header="3.0" />
</ContextMenu>
代码隐藏:
private void ContextMenu_OnOpened(object sender, RoutedEventArgs e)
{
var contextMenu = (ContextMenu)sender;
var firstItem = (MenuItem)contextMenu.Items[0];
// Must create new array of existing menu items
// to be able to edit existing context menu during loop enumeration.
var allItems = contextMenu.Items.Cast<MenuItem>().ToArray();
foreach (var item in allItems)
{
if (item.Header.ToString() == "1.1" || item.Header.ToString() == "1.2")
{
// Add menu item with the same header into another item as sub-item
firstItem.Items.Add(new MenuItem { Header = item.Header });
// Remove item from root level.
contextMenu.Items.Remove(item);
}
}
}
在这里,我使用了特定标题文本(“1.1”和“1.2”)的条件,并将项目放在第一个菜单项中,但您可以在特定程序中实现所需的任何逻辑。
Opened
事件在每次上下文菜单打开时触发,因此您可以在当前时刻进行所需的任何动态更改。
更新1
以下是涉及 ItemsSource
绑定(bind)的示例。优点是您可以只与 MenuItemsCollection
交互,而不必担心 ContextMenu
对象本身、它的视觉项目和其他细节。
Xaml:
<TextBox>
<TextBox.ContextMenu>
<ContextMenu Opened="ContextMenu_OnOpened" ItemsSource="{Binding MenuItemsCollection}" />
</TextBox.ContextMenu>
</TextBox>
代码隐藏:
public ObservableCollection<MenuItem> MenuItemsCollection { get; set; } = new ObservableCollection<MenuItem>
{
new MenuItem { Header = "1.0" },
new MenuItem { Header = "1.1" },
new MenuItem { Header = "1.2" },
new MenuItem { Header = "2.0" },
new MenuItem { Header = "3.0" },
};
private void ContextMenu_OnOpened(object sender, RoutedEventArgs e)
{
var firstItem = this.MenuItemsCollection[0];
var allItems = this.MenuItemsCollection.ToArray();
foreach (var item in allItems)
{
if (item.Header.ToString() == "1.1" || item.Header.ToString() == "1.2")
{
firstItem.Items.Add(item);
this.MenuItemsCollection.Remove(item);
}
}
}
更新2
如果您想每次都直接将新项目列表分配给 ContextMenu
元素:
private void ContextMenu_OnOpened(object sender, RoutedEventArgs e)
{
// var actualItems = GetListOfItemsAnyWayYouNeed();
var actualItems = new List<MenuItem>
{
new MenuItem {
Header = "1.0",
Items =
{
new MenuItem { Header = "1.1" },
new MenuItem { Header = "1.2" } }
},
new MenuItem { Header = "2.0" },
new MenuItem { Header = "3.0" },
};
_oContextMenu.ItemsSource = actualItems;
}
结论
将值设置为 ItemsSource
后,您不能再操作 _oContextMenu
,至少它的 Items
属性 - 您会从您的第一条评论。这意味着你不能像我原来的答案那样做,因为你直接分配给 ItemsSource
。
您尝试将 oMenuItemList
直接设置为 _oContextMenu.ItemsSource
(类似于 Update2 中显示的内容),但之后您无法操作 _oContextMenu.Items
。您只能操作您的 oMenuItemList
(如果您将其保存在全局变量中),但它不会更改实际菜单内容,因为您的列表不是 ObservableCollection
。
如果你仍然想在代码中做所有事情,试试这个:
ObservableCollection<object> oMenuItemList { get; set; }
...
oMenuItemList = GetContextMenuItems(sMenuItems);
//the function
private ObservableCollection<object> GetContextMenuItems(string sMenuItems)
{
//returns the ObservableCollection
}
_oContextMenu.ItemsSource = oMenuItemList;
您在 oMenuItemList
(但不是在 _oContextMenu.Items
) 中所做的任何更改都将应用到实际的上下文菜单中。
但无论如何,最好的方法仍然是按照 Update1 中的描述进行操作。
关于c# - WPF:如何循环遍历 ContextMenu 以重新排列其中的项目或将菜单项作为子项添加到菜单项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37452800/