C# 将ToolStripMenuItems从不同MEF插件合并到一个MenuStrip中
目前,我尝试将不同的C# 将ToolStripMenuItems从不同MEF插件合并到一个MenuStrip中,c#,winforms,plugins,mef,C#,Winforms,Plugins,Mef,目前,我尝试将不同的ToolStripMenuItems合并为一个MenuStrip。因此,我创建了一个名为IMenu的接口。这包括来自MEF插件的ToolStripMenuItem,应该加载到主窗口Menustrip中。问题是,如果我运行应用程序,我会在MenuStrip中找到两个同名的下拉元素。但是我想要的是,我可以将MEF插件的菜单绑定到应用程序的MenuStrip中,而无需双重输入,例如。 如何为MEF插件创建一个好的菜单结构 示例:我已从主应用程序中获取此条目 文件 |-->新的 |-
ToolStripMenuItems
合并为一个MenuStrip
。因此,我创建了一个名为IMenu
的接口。这包括来自MEF插件的ToolStripMenuItem
,应该加载到主窗口Menustrip中。问题是,如果我运行应用程序,我会在MenuStrip
中找到两个同名的下拉元素。但是我想要的是,我可以将MEF插件的菜单绑定到应用程序的MenuStrip中,而无需双重输入,例如。
如何为MEF插件创建一个好的菜单结构
示例:我已从主应用程序中获取此条目
文件|-->新的
|-->保存
|-->导入
|-->出口 然后我创建了一个插件,用于导入/导出特定类型。因此,我必须在菜单中动态添加导入/导出下的条目。但是怎么做呢?你的解决方案怎么样 文件
|-->新的
|-->保存
|-->导入
|----->到Word
|-->导出
|----->从字里行间 这是我的代码: 首先是插件的接口
public interface IMenu
{
ToolStripMenuItem ToolStripItem { get; }
}
这是一个菜单项的插件示例
帮助|-->更新 这是另一个MEF插件,它也有根元素“Help” 在我的主窗体中,我将所有内容添加到MenuStrip
foreach (var item in MenuItems)
{
this.menuStrip1.Items.Add(item.ToolStripItem);
}
ToolStripMenuItems
不会自动合并?我非常怀疑是否有自动功能可以做到这一点,因此下面是我如何处理手动解决方案的。有一个陷阱,那就是ToolStripItem
在任何时候都只能有一个父项。因此,将其添加到现有菜单会将其从其他菜单中删除,您需要考虑到这一点(在我的方法中,通过检查项目是否已经有所有者来完成)。如果这是一个问题,您需要首先克隆子项
编辑:我意识到您可能需要一个递归函数,所以我替换了代码。类MenuItem2包含帮助/speichen/另存为/关于项
public Form1()
{
InitializeComponent();
List<IMenu> menuItems = new List<IMenu>() { new UpdateMenuItems(), new MenuItem(), new MenuItem2() };
MergeMenus(this.menuStrip1.Items, menuItems.Select(m => m.ToolStripItem));
}
/// <summary>
/// Recursive function that merges two ToolStripItem trees into one
/// </summary>
/// <param name="existingItems">Collection of existing ToolStripItems</param>
/// <param name="newItems">Collection of new ToolStripItems. IEnumerable instead of ToolStripItemCollection to allow for items without an owner</param>
private void MergeMenus(ToolStripItemCollection existingItems, IEnumerable<ToolStripItem> newItems)
{
int count = newItems.Count();
int removedFromCollection = 0; // keep track of items that are removed from the newItems collection
for (int i = 0; i < count; i++)
{
ToolStripItem newItem = newItems.ElementAt(i - removedFromCollection);
bool merged = false;
string key = newItem.Name; // the items are identified and compared by its name
if (existingItems.ContainsKey(key))
{
ToolStripItem existingItem = existingItems[key];
if (existingItem != null && existingItem.GetType().Equals(newItem.GetType()))
{
// check if the matching items are ToolStripMenuItems. if so, merge their children recursively
if (newItem is ToolStripMenuItem)
MergeMenus(((ToolStripMenuItem)existingItem).DropDownItems, ((ToolStripMenuItem)newItem).DropDownItems.Cast<ToolStripItem>());
// do not add this particular item (existing item with same name and type found)
merged = true;
}
}
if (!merged) // newItem does not exist in existingItems (or not as the same type)
{
// if there was an owner, the item will be removed from the collection and the next element's index needs to be adjusted
if (newItem.Owner != null)
removedFromCollection++;
// add item to the existing tree
existingItems.Add(newItem);
}
}
}
public Form1()
{
初始化组件();
List menuItems=new List(){new UpdateMenuItems(),new MenuItem(),new MenuItem2()};
合并菜单(this.menuStrip1.Items,menuItems.Select(m=>m.ToolStripItem));
}
///
///将两个ToolStripItem树合并为一个的递归函数
///
///现有ToolStripItems的集合
///新ToolStripItems的集合。IEnumerable代替ToolStripItemCollection,以允许没有所有者的项
私有void合并菜单(ToolStripItemCollection existingItems、IEnumerable newItems)
{
int count=newItems.count();
int removedFromCollection=0;//跟踪从newItems集合中删除的项
for(int i=0;i
经过测试,似乎有效:
我实现了一个主菜单,通过IMenuService使用MVVM和Unity。我在同一主题上发布了我自己问题的完整答案(但针对的是菜单而不是工具条)。我认为您可以为ToolStrip做一些与我在代码中所做的非常相似的事情 请参阅以下答案:
嗨,艾伦,谢谢你的回答和MVVM版本,但我在winforms中搜索了一个没有开销的版本:)但是大thx
foreach (var item in MenuItems)
{
this.menuStrip1.Items.Add(item.ToolStripItem);
}
public Form1()
{
InitializeComponent();
List<IMenu> menuItems = new List<IMenu>() { new UpdateMenuItems(), new MenuItem(), new MenuItem2() };
MergeMenus(this.menuStrip1.Items, menuItems.Select(m => m.ToolStripItem));
}
/// <summary>
/// Recursive function that merges two ToolStripItem trees into one
/// </summary>
/// <param name="existingItems">Collection of existing ToolStripItems</param>
/// <param name="newItems">Collection of new ToolStripItems. IEnumerable instead of ToolStripItemCollection to allow for items without an owner</param>
private void MergeMenus(ToolStripItemCollection existingItems, IEnumerable<ToolStripItem> newItems)
{
int count = newItems.Count();
int removedFromCollection = 0; // keep track of items that are removed from the newItems collection
for (int i = 0; i < count; i++)
{
ToolStripItem newItem = newItems.ElementAt(i - removedFromCollection);
bool merged = false;
string key = newItem.Name; // the items are identified and compared by its name
if (existingItems.ContainsKey(key))
{
ToolStripItem existingItem = existingItems[key];
if (existingItem != null && existingItem.GetType().Equals(newItem.GetType()))
{
// check if the matching items are ToolStripMenuItems. if so, merge their children recursively
if (newItem is ToolStripMenuItem)
MergeMenus(((ToolStripMenuItem)existingItem).DropDownItems, ((ToolStripMenuItem)newItem).DropDownItems.Cast<ToolStripItem>());
// do not add this particular item (existing item with same name and type found)
merged = true;
}
}
if (!merged) // newItem does not exist in existingItems (or not as the same type)
{
// if there was an owner, the item will be removed from the collection and the next element's index needs to be adjusted
if (newItem.Owner != null)
removedFromCollection++;
// add item to the existing tree
existingItems.Add(newItem);
}
}
}