- PR -

ToolStripとContextMenuStripでメニュー項目を共有

1
投稿者投稿内容
ichipaso
会議室デビュー日: 2007/09/20
投稿数: 3
投稿日時: 2007-09-20 16:41
いつもお世話になります。VS2005C#で開発しています。

ToolStripとContextMenuStripで同じメニュー項目を共有したいのですが、
1つのToolStripMenuItemのインスタンスでは
最後にメニュー項目を追加したコントロールのみ、メニュー項目が表示されます。
(下記コードの※1と※2を逆にしても同じ)

各コントロール個別にToolStripMenuItemのインスタンスを作成すれば問題ありません。
この場合、ToolStripMenuItemの派生クラスを作るなどすれば
メニュー項目の共有はできますが、
なぜ1つのToolStripMenuItemのインスタンスではできないのでしょうか?

以上、よろしくお願いします。

コード:
public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();

    ToolStripMenuItem item = new ToolStripMenuItem("項目1");
    this.ContextMenuStrip = new ContextMenuStrip();
    this.ContextMenuStrip.Items.Add(item);   // ※1 "項目1"は表示されない
    this.Controls.Add(new ToolStrip(item));  // ※2 "項目1"は表示される
  }
}


まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-09-20 22:10
仕様です。

#以下、半分予想ですが。

OwnerやContainerプロパティがあります。
Addメソッド内?でそれらがすでに別の親を保持している場合に、まずそのコレクションなりから削除しているはずです。
希望している動作を実現するにはこのような親を表すものを複数保持する必要が出てきます。
また、それらがすべてNullになるまで破棄することも出来なくなりますね。

で、今回のようなことをおこなう場合は、通常、Cloneメソッドで複製を作成します。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-09-20 22:44
そうではなくて、実装されていなければできないだけでしょう。

引用:

ichipasoさんの書き込み (2007-09-20 16:41) より:

なぜ1つのToolStripMenuItemのインスタンスではできないのでしょうか?


この次元ならば 「インスタンスだからです」 になるでしょう。 正しくは「共有したい機能が実装されていないインスタンスが生成されるからです」 と答えた方が正しいでしょうか。

なぜ 「Parent や Owner」 に関係なくこの回答になったかですが、

引用:

ToolStripMenuItemの派生クラスを作るなどすればメニュー項目の共有はできますが、


こちらが "なぜ" 成り立つのかを説明できないからです。 こちらは 「共有したい機能が実装されているインスタンスが生成されるからです」 という回答になります。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ichipaso
会議室デビュー日: 2007/09/20
投稿数: 3
投稿日時: 2007-09-21 08:49
皆さん回答ありがとうございます。

1つのインスタンスにこだわったのは、
値型変数のように記述できればという単純な考えからです。

ただ、既に割り当て済みのOwnerがあるインスタンスをAddする場合、
Add側で例外をスローしてほしいと思うのは自分だけでしょうか?

結論としてインスタンスを共有できないのであれば、
型で共有する方法にしました。

いろいろありがとうございました。

コード:
public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();

    this.ContextMenuStrip = new ContextMenuStrip();
    this.ContextMenuStrip.Items.Add(new MyItem1());
    this.Controls.Add(new ToolStrip(new MyItem1()));
  }
}

public class MyItem1 : ToolStripMenuItem
{
  public MyItem1() : base()
  {
    this.Text = "項目1";
    this.Click += delegate { };
  }
}


じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-09-21 10:53
派生クラスを作らなくとも、デコレータ クラスを作りイベント ハンドラ等を共有すれば擬似的に自分の欲しい機能を追加することはできます。 まあ手間はあまり変わりません。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ichipaso
会議室デビュー日: 2007/09/20
投稿数: 3
投稿日時: 2007-09-21 14:39
>じゃんぬねっと様
アドバイスありがとうございます。

デコレータ??
どうやら調べてみるとデザインパターンの1つみたいですね。
デザインパターンについては、全く知識がないのでこれから勉強します。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)