2

ToolStripMenuItems現在、私は別のものを1つにマージしようとしていMenuStripます。そのため、と呼ばれるインターフェイスを作成しましたIMenu。これにはToolStripMenuItemMEFプラグインからのものが含まれ、Main-Window-Menustripにロードする必要があります。問題は、アプリケーションを実行するMenuStripと、同じ名前の2つのDropDown要素を取得することです。しかし、私が欲しいのは、MEFプラグインのメニューをダブルエントリなしでアプリケーションのMenuStripにバインドできることです。たとえば、MEFプラグインの優れたメニュー構造を作成するにはどうすればよいですか。

例:メインアプリケーションからこのエントリがあります

ファイル
|->新規
|->保存
|->インポート
|->エクスポート

次に、特定のタイプをインポート/エクスポートするためのプラグインを作成します。そのため、インポート/エクスポートの下のエントリを動的にメニューに追加する必要があります。しかし、どのように?あなたの解決策はどうですか?

ファイル
|->新規
|->保存
|->インポート
|----->Wordへ
|->エクスポート
|----->Wordから

ここに私のコードがあります:最初にプラグインのインターフェース

public interface IMenu
{
  ToolStripMenuItem ToolStripItem { get; }
}

これはメニュー項目のプラグインの例です

ヘルプ
|->更新

[Export(typeof(IMenu))]
class UpdateMenuItems : IMenu
{
  System.Windows.Forms.ToolStripMenuItem helpMenuItem;
  System.Windows.Forms.ToolStripMenuItem updateMenuItem;

  public System.Windows.Forms.ToolStripMenuItem ToolStripItem
  {
    get { return helpMenuItem; }
  }

  public UpdateMenuItems()
  {
    InitializeComponent();
  }

  private void InitializeComponent()
  {
    this.updateMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.updateMenuItem.Name = "Update";
    this.updateMenuItem.Size = new System.Drawing.Size(94, 20);
    this.updateMenuItem.Text = "Update";
    this.updateMenuItem.MergeIndex = 1;
    this.updateMenuItem.MergeAction = System.Windows.Forms.MergeAction.Insert;
    this.updateMenuItem.Click += updateMenuItem_Click;

    this.helpMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.helpMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
          this.updateMenuItem});
    this.helpMenuItem.Name = "aboutToolStripMenuItem";
    this.helpMenuItem.Size = new System.Drawing.Size(44, 20);
    this.helpMenuItem.MergeAction = System.Windows.Forms.MergeAction.Insert;
    this.helpMenuItem.Text = "Help";

  }

  void updateMenuItem_Click(object sender, EventArgs e)
  {
    UpdateController update = new UpdateController();
    update.Execute();
  }    

これは、ルート要素「ヘルプ」を持つ別のMEFプラグインです。

[Export(typeof(IMenu))]
class MenuItem : IMenu
{
  public ToolStripMenuItem ToolStripItem
  {
    get { return testItem; }
  }

  private System.Windows.Forms.ToolStripMenuItem testItem;
  private System.Windows.Forms.ToolStripMenuItem unterpunk1;
  private System.Windows.Forms.ToolStripMenuItem unterpunk2;

  public MenuItem()
  {
    InitializeComponent();
  }

  public void InitializeComponent()
  {
    this.testItem = new System.Windows.Forms.ToolStripMenuItem();
    this.testItem.Name = "aboutToolStripMenuItem";
    this.testItem.Size = new System.Drawing.Size(94, 20);
    this.testItem.Text = "Help";
    this.testItem.Click += testItem_Click;

    unterpunk1 = new ToolStripMenuItem();
    unterpunk1.Text = "Speichern";
    unterpunk1.MergeAction = MergeAction.Insert;
    unterpunk1.MergeIndex = 1;
    testItem.DropDownItems.Add(unterpunk1);

    unterpunk2 = new ToolStripMenuItem();
    unterpunk2.Text = "Prüfen";
    unterpunk2.MergeAction = MergeAction.Insert;
    unterpunk2.MergeIndex = 2;
    testItem.DropDownItems.Add(unterpunk2);

  }

  void testItem_Click(object sender, EventArgs e)
  {
    //
  }

私のメインフォームでは、すべてをMenuStripに追加します。

  foreach (var item in MenuItems)
  {
    this.menuStrip1.Items.Add(item.ToolStripItem);
  }

自動的にToolStripMenuItemsマージしませんか?

4

2 に答える 2

3

それを行う自動機能があるかどうかは非常に疑わしいので、手動ソリューションにアプローチする方法は次のとおりです。落とし穴が1つあります。それは、ToolStripItem缶にはいつでも1人の親しかいないということです。したがって、既存のメニューに追加すると、他のメニューから削除されます。これを考慮する必要があります(私の方法では、アイテムに既に所有者がいるかどうかを確認して行います)。それが問題になる場合は、最初にサブアイテムのクローンを作成する必要があります。

編集:おそらく再帰関数が必要になることに気付いたので、コードを置き換えました。クラスMenuItem2には、Help / Speichern / Save As/Aboutアイテムが含まれています。

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

テストされ、動作しているようです:

ここに画像の説明を入力してください

于 2013-02-20T19:03:54.027 に答える
2

IMenuServiceを介してMVVMとUnityを使用して、メインメニューを実装しました。私はこの同じトピックに関する自分の質問に対するかなり完全な回答を投稿しました(ただし、ツールストリップではなくメニューについて)。ToolStripに対して、私がコードで行ったことと非常によく似たことができると思います。

次の回答を参照してください。

MVVMでメニューを生成するためのDataTemplate

于 2013-02-21T07:15:33.417 に答える