1. 記事の背景
1. ポリモーフィズムの簡単な説明
- ポリモーフィズムは、異なる結果を伴う同じ動作です。たとえば、どれも「吠える」のですが、犬と猫では鳴き声や音波が異なります。
- ポリモーフィズムはオーバーロードと切り離すことができず、メソッドのオーバーロードを使用して、派生クラスで独自の機能を実現します。C# では、ユーザー定義型を含むすべての型が Object から継承されるため、すべての型はポリモーフィックです。
2. 開発における多態性の適用
- 私が初めてオブジェクト指向プログラミングを学び始めたとき、ポリモーフィズムについての理解は非常に抽象的でした。私と同じように、ほとんどの学生は、必要な関数を書くために基本的な文法を選択的にスキップして学習していると思います。
学習が深まるにつれて、書かれたソフトウェアの複雑さが増し、徐々に C# ではポリモーフィズムが蔓延しているように感じますが、これはオブジェクト指向プログラミングを学習する際に避けなければならない落とし穴です。 - フレームワークを始めるときは、ポリモーフィズムが必須です。
- 後で時間があるときに、開発フレームワークにおけるポリモーフィズムの概念と実践を公開します。
3. ToolSplit を使用する理由
- 今日は、これまでのプログラムを整理するにあたり、中国語と英語の切り替え機能を最適化したのですが、その感想をもとに記事をお送りしました。ToolSplit はポリモーフィズムを使用して実装されており、これを理解することでポリモーフィズムをよく理解できます。
- ToolSplit は Microsoft がパッケージ化したコントロールですが、基本的にアプリケーションレベルでの開発のみを行っており、アプリケーションだけにとどまらずホイールがどのように作られているかを理解する必要があります。
- アプリケーションは開発原理を理解し、自分の能力を最大限に発揮するために自ら開発を適用する必要があります。
- トラバースでは、どのような種類のアイテムがトラバースされるのかを知る必要があるため、練習して理解を深められるだけです
2. 関連クラスのご紹介(公式より抜粋)
1.制御
- 承:オブジェクト - MarshalByRefObject - コンポーネント - コントロール
- Derivation : 基本的にすべてのコントロールの直接または間接的な親クラス
- 機能: 視覚的な表現を持つコンポーネントであるコントロールの基本クラスを定義します。
- スレッド セーフ
: コントロールへのハンドルが作成されている場合、BeginInvoke(Delegate)、EndInvoke(IAsyncResult)、InvokeRequiredInvoke(Delegate)、および CreateGraphics()のメンバーのみがスレッド セーフです。バックグラウンド スレッドでコントロールのハンドルを作成する前に CreateGraphics() を呼び出すと、
不正なクロススレッド呼び出しが発生する可能性があります。
2.ツールストリップ
- 継承:オブジェクト - MarshalByTefObject - コンポーネント - コントロール -
ScrollableControl - ToolStrip - 派生: System.Windows.Forms.ToolStripDropDown、
System.Windows.Forms.MenuStrip等 - 機能: メニュー バー。第 1 レベルのメニューのコンテナを提供します。これは通常、ToolStripContainer (上部パネル) コントロールとともに使用され、ToolStrip を ToolStripContainer に追加してから、ToolStripContainer をフォームのコントロール コレクションに追加します。
- 属性: ToolStripItemCollection Items、第 1 レベルのメニュー バーのコントロール コレクション
3.ToolStripItemCollection
- 継承: オブジェクト - ArrangedElementCollection - ToolStripItemCollection 派生 :
ListBindableAttribute - 機能: ツール ストリップ項目コレクション クラス。ToolStrip.Items のタイプ。ToolStripItem タイプのコレクション クラスを格納するために使用されます。
- 属性: プライベート ToolStripItem[] タイプ属性 A があり、追加されたメニュー関数を保存し、インデクサーのインデックス付けに使用されます。
public virtual ToolStripItem this[int index] {
get; }
public virtual ToolStripItem this[string key] {
get; }
- メソッド: Add - ToolStripItem をプライベート プロパティ A に追加します。オーバーロード4。
4.ツールストリップアイテム
- 承:オブジェクト - MarshalByRefObject - コンポーネント - BindableComponent - ToolStripItem
- 派生: 子メニュー関数なし - ToolStripButton、ToolStripControlHost、ToolStripLabel、ToolStripSeparator、子メニュー関数を持つ親クラス ToolStripDropDownItem
- Function : 第 1 レベルのメニューのすべての関数の親クラスの抽象
5.ツールストリップドロップダウン
- 継承:オブジェクト - MarshalByRefObject - コンポーネント - コントロール -
ScrollableControl - ToolStrip - ToolStripDropDown - 派生:System.Windows.Forms.ToolStripDropDownMenu、
System.Windows.Forms.ToolStripOverflow - 機能
: ToolStripDropDownButton をクリックしたときに、ユーザーが表示されたリストから 1 つの項目を選択できるようにするコントロールを表します。2 番目のレベルより上のメニューのコンテナとして理解できます。 - 属性: ToolStripItemCollection Items、セカンダリ メニューの上にあるコントロールのコレクション
6.ツールストリップドロップダウン項目
- 継承: オブジェクト - MarshalByRefObject - ToolStripItem -
ToolStripDropDownItem 第 2 レベルのメニューの親クラスは第 1 レベルのメニューの親クラスから派生していることがわかり、ToolStripDropDownButton などの第 2 レベルのメニューの関数は次のようになります。第 1 レベルのメニューにも追加されます - 派生: サブレベルのメニュー関数クラスがあります - ToolStripDropDownButton、ToolStripMenuItem、ToolStripSplitButton
- 機能: 子メニュー関数を持つ親クラス: ToolStripDropDown、ToolStripDropDownButton、または ToolStripMenuItem コントロール。ToolStripSplitButton コントロールの基本機能を表示します。子メニューを提供しない ToolStripItem と同様
3. ケース
1. 動的宣言メニュー(もちろん設定により追加可能)
private ToolStrip toolStrip1; //菜单栏
private ToolStripContainer toolStripContainer1; //面板,放于顶部存放toolStrip1
private ToolStripDropDown dropDown; //按扭ToolStripDropDownButton弹出来的子菜单容器,二级菜单
private ToolStripDropDown dropDown2; //按扭ToolStripDropDownButton弹出来的子菜单容器,三级菜单
2. 動的メニューにサブ項目を追加します (同様に、構成によって追加できます)
private void Form1_Load(object sender, EventArgs e)
{
toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
toolStrip1 = new System.Windows.Forms.ToolStrip();
dropDown = new ToolStripDropDown();
dropDown2 = new ToolStripDropDown();
//一级菜单
//创建各种类型的子项
ToolStripButton toolStripButton = new ToolStripButton();
toolStripButton.Text = "1-button";
ToolStripLabel toolStripLabel = new ToolStripLabel();
toolStripLabel.Text = "1-text";
ToolStripDropDownButton toolStripDropDownButton = new ToolStripDropDownButton();
toolStripDropDownButton.Text = "1-DownButton";
ToolStripSplitButton toolStripSplitButton = new ToolStripSplitButton();
toolStripSplitButton.Text = "1-splitButton";
ToolStripTextBox toolStripTextBox = new ToolStripTextBox();
toolStripTextBox.Text = "1-textBox";
ToolStripComboBox toolStripComboBox = new ToolStripComboBox();
toolStripComboBox.Text = "1-ComboBox";
//这里使用了参数为string类型的重载
toolStrip1.Items.Add("1-One");
//下面使用的是参数为ToolStripItrm的重载
toolStrip1.Items.Add(toolStripButton);
toolStrip1.Items.Add(toolStripLabel);
toolStrip1.Items.Add(toolStripDropDownButton); //将弹出二级菜单
toolStrip1.Items.Add(toolStripSplitButton);
toolStrip1.Items.Add(toolStripTextBox);
toolStrip1.Items.Add(toolStripComboBox);
// 将ToolStrip添加到ToolStripContainer的顶部面板
toolStripContainer1.TopToolStripPanel.Controls.Add(toolStrip1);
toolStrip1.Dock = DockStyle.Fill;
// 把顶部面板添加到窗体的控件集合里
Controls.Add(toolStripContainer1);
toolStripContainer1.Width = this.Width;
//二级菜单
//创建二级各种类型的子项
ToolStripButton toolStripButton2 = new ToolStripButton();
toolStripButton2.Text = "2-button";
ToolStripLabel toolStripLabel2 = new ToolStripLabel();
toolStripLabel2.Text = "2-text";
ToolStripDropDownButton toolStripDropDownButton2 = new ToolStripDropDownButton();
toolStripDropDownButton2.Text = "2-DownButton";
ToolStripSplitButton toolStripSplitButton2 = new ToolStripSplitButton();
toolStripSplitButton2.Text = "2-splitButton";
ToolStripTextBox toolStripTextBox2 = new ToolStripTextBox();
toolStripTextBox2.Text = "2-textBox";
ToolStripComboBox toolStripComboBox2 = new ToolStripComboBox();
toolStripComboBox2.Text = "2-ComboBox";
//添加二级菜单项到二级菜单容器
dropDown.Items.Add(toolStripButton2);
dropDown.Items.Add(toolStripLabel2);
dropDown.Items.Add(toolStripDropDownButton2);
dropDown.Items.Add(toolStripSplitButton2);
dropDown.Items.Add(toolStripTextBox2);
dropDown.Items.Add(toolStripComboBox2);
//把二级菜单容器绑定到一级菜单某个项
toolStripDropDownButton.DropDown = dropDown;
//三级菜单
//创建三级各种类型的子项
ToolStripButton toolStripButton3 = new ToolStripButton();
toolStripButton3.Text = "3-button";
ToolStripLabel toolStripLabel3 = new ToolStripLabel();
toolStripLabel3.Text = "3-text";
ToolStripDropDownButton toolStripDropDownButton3 = new ToolStripDropDownButton();
toolStripDropDownButton3.Text = "3-DownButton";
ToolStripSplitButton toolStripSplitButton3 = new ToolStripSplitButton();
toolStripSplitButton3.Text = "3-splitButton";
ToolStripTextBox toolStripTextBox3 = new ToolStripTextBox();
toolStripTextBox3.Text = "3-textBox";
ToolStripComboBox toolStripComboBox3 = new ToolStripComboBox();
toolStripComboBox3.Text = "3-ComboBox";
//添加三级菜单项到三级菜单容器
dropDown2.Items.Add(toolStripButton3);
dropDown2.Items.Add(toolStripLabel3);
dropDown2.Items.Add(toolStripDropDownButton3);
dropDown2.Items.Add(toolStripSplitButton3);
dropDown2.Items.Add(toolStripTextBox3);
dropDown2.Items.Add(toolStripComboBox3);
//把三级菜单容器绑定到二级菜单某个项
toolStripDropDownButton2.DropDown = dropDown2;
}
3. 第 1 レベルのメニューを移動します。
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
//遍历一级菜单
foreach (ToolStripItem item in toolStrip1.Items)
{
listBox1.Items.Add(item.Text);
//判断该项是否为二级菜单
if (item is ToolStripDropDownItem)
{
listBox1.Items.Add("");
listBox1.Items.Add("以下是" + item.Text + "的子项☞");
ToolStripDropDownItem toolStripDropDownItem = item as ToolStripDropDownItem;
TracerseToolStrip(toolStripDropDownItem);
listBox1.Items.Add("以上是" + item.Text + "的子项☜");
listBox1.Items.Add("");
}
}
}
4. 第 2 レベル以降のメニューの移動
/// <summary>
/// 递归遍历二级以上菜单
/// </summary>
/// <param name="toolStripItem"></param>
private void TracerseToolStrip(ToolStripDropDownItem toolStripItem)
{
foreach (ToolStripItem item in toolStripItem.DropDownItems)
{
listBox1.Items.Add(item.Text);
//判断该项是否为二级菜单
if (item is ToolStripDropDownItem)
{
listBox1.Items.Add("");
listBox1.Items.Add("以下是" + item.Text + "的子项☞");
ToolStripDropDownItem toolStripDropDownItem = item as ToolStripDropDownItem;
TracerseToolStrip(toolStripDropDownItem);
listBox1.Items.Add("以上是" + item.Text + "的子项☜");
listBox1.Items.Add("");
}
}
}
}
4. 設定フォームは次のとおりです
4. 実行結果は次のとおりです
いくらでも、どれだけでも、うまく横断できます
4. まとめ
1. 型分析
- 非常に面倒なので、クラス図を描かずに簡単に説明します。
- コンテナコントロールクラス:ToolStrip、ToolStripDropDown、前者はメニューバー全体のコンテナ(つまり、第1レベルのメニューバーコンテナ)、後者は第2レベル以上のメニューコンテナ、前者は親クラス後者の。これらには、メニュー関数クラスを格納する共通の属性 Items があります。
- メニュー関数クラス: 主に 2 つのカテゴリに分けられます。1 つのクラスには、ToolStripButton、ToolStripControlHost、ToolStripLabel、ToolStripSeparator などのサブレベル メニューがありません。その親クラスは ToolStripItem で、もう 1 つのクラスには、ToolStripDropDownButton などの独自の子があります。 ToolStripMenuItem、ToolStripSplitButton は、親クラスが ToolStripDropDownItem であり、同じ属性 DropDown を持ち、独自の子メニュー コンテナーを格納します。
- メニュー関数クラスのコレクション クラス: ToolStripItemCollection。このクラスは、コンテナ ToolStrip および ToolStripDropDown のプロパティ Items の型です。これには、ToolStripItem[] タイプの属性 A リストがあり、ToolStripItem タイプを属性 A リストに追加するために使用される Add メソッドのオーバーロードがあり、属性 A リストの値を取得するインデクサーを定義します。
2. ポリモーフィズムの美しさ
- ToolStrip コントロールを自分で設定する場合は、まず要件を明確にする必要があります: 多くの機能を持つボタンを追加でき、一部のボタンには独自のサブメニューがあります。同様に、サブメニューにも同じ種類のボタンを追加できます。ワイヤレス マトリョーシカ...
- コンテナーから始めて、コントロールからコンテナーが見えるため、2 種類のコンテナーを持つことをお勧めします。上記のコンテナーはポップアップ Window スタイルの配置であり、ToolStripItemCollection 型の属性を持つ Items など、2 つのコンテナーには類似点が多すぎるため、ポリモーフィズムを使用してそれらの共通点を同じ親クラスに書き込みます。
これにより、ToolStripItem と ToolStripDropDownItem およびその派生クラスを理解することができ、ToolStripItem は ToolStripDropDownItem の親クラスであるため、ToolStripDropDownItem は特別な ToolStripItem であることが理解できます。これは、ToolStripItem のプロパティを継承するだけでなく、独自のプロパティ (DropDown) も持つためです。)
3. 再帰的な設定
ここには、主に第 1 レベルのメニューの特殊性を考慮した 2 つのトラバースがあります。もちろん、ToolStrip 自体は ToolStripDropDown の親クラスであり、1 回の再帰で完全に走査できます。興味のある学生は自分で試してみることができます。
注:
この記事を転載するには出典を示す必要があります。
グ・ジペン: [email protected]