C# Control Basics 1 | Understanding and traversing the menu bar control ToolSplit from a polymorphic perspective

1. Background of the article

1. Simple description of polymorphism

  • Polymorphism is the same behavior with different consequences. For example, they all "bark", but dogs and cats have different barks and sound waves.
  • Polymorphism is inseparable from overloading, using overloading a method to realize its own functions in derived classes. In C#, every type is polymorphic because all types, including user-defined types, inherit from Object.

2. Application of polymorphism in development

  • When I first started learning object-oriented programming, my understanding of polymorphism was quite abstract. I believe that most of the students, like me, selectively skip and learn the basic grammar to write the functions they want.
    With the deepening of learning, the complexity of the written software increases, and gradually I feel that polymorphism is ubiquitous in C#, and it is a pit that must be avoided when learning object-oriented programming.
  • When we start with frameworks, polymorphism is a must.
  • Later, when I have time, I will publish the concept and practice of polymorphism in the development framework.

3. Why ToolSplit

  • Today, when sorting out the previous programs, I optimized the Chinese-English switching function, and I sent an article based on my feelings. ToolSplit is implemented using polymorphism, and understanding it will give you a good understanding of polymorphism.
  • ToolSplit is a control packaged by Microsoft. In principle, we are only developing at the application level, and we should not stop at the application, but also understand how the wheel is made.
  • The application needs to understand the development principle, and the development needs to be applied by oneself in order to maximize one's ability.
  • In traversal, we must know what type of item is traversed, so it just allows us to practice and deepen our understanding

2. Introduction of related classes (excerpt from official)

1.Control

  • 继承:Object - MarshalByRefObject - Component - Control
  • Derivation : basically the direct or indirect parent class of all controls
  • Function : Defines the base class of controls, which are components with visual representations.
  • Thread Safety : If a handle to the control has been created, only the following members are thread safe: BeginInvoke(Delegate), EndInvoke(IAsyncResult), InvokeRequiredInvoke(Delegate),
    and CreateGraphics(). Calling CreateGraphics() before creating the control's handle on a background thread
    may result in an illegal cross-thread call.

2.ToolStrip

  • 继承:Object - MarshalByTefObject - Component - Control -
    ScrollableControl - ToolStrip
  • Derived from : System.Windows.Forms.ToolStripDropDown,
    System.Windows.Forms.MenuStrip, etc.
  • Function : menu bar, which provides a container for the first-level menu. It is usually used with the ToolStripContainer (top panel) control, add the ToolStrip to the ToolStripContainer, and then add the ToolStripContainer to the control collection of the form.
  • Attribute : ToolStripItemCollection Items, the control collection of the first-level menu bar

3.ToolStripItemCollection

  • Inheritance : Object - ArrangedElementCollection - ToolStripItemCollection Derivation:
    ListBindableAttribute
  • Function : tool strip item collection class, the type of ToolStrip.Items, used to store the collection class of ToolStripItem type.
  • Attribute : It has a private ToolStripItem[] type attribute A, which stores the added menu function and is used for the indexer to index the indexer:
public virtual ToolStripItem this[int index] {
    
     get; }     
public virtual ToolStripItem this[string key] {
    
     get; }  
  • Method : Add - Adds a ToolStripItem to private property A. Overload 4.

4.ToolStripItem

  • 继承:Object - MarshalByRefObject - Component - BindableComponent - ToolStripItem
  • Derivation : No child menu function - ToolStripButton, ToolStripControlHost, ToolStripLabel, ToolStripSeparator, parent class ToolStripDropDownItem with child menu function
  • Function : the parent class abstract of all functions of the first-level menu

5.ToolStripDropDown

  • 继承:Object - MarshalByRefObject - Component - Control -
    ScrollableControl - ToolStrip - ToolStripDropDown
  • 派生:System.Windows.Forms.ToolStripDropDownMenu 、
    System.Windows.Forms.ToolStripOverflow
  • Function : Represents a control that allows the user
    to select a single item from the displayed list when the ToolStripDropDownButton is clicked. It can be understood as a container for menus above the second level
  • Attribute : ToolStripItemCollection Items, a collection of controls above the secondary menu

6.ToolStripDropDownItem

  • Inheritance : Object - MarshalByRefObject - ToolStripItem -
    ToolStripDropDownItem. It can be seen that the parent class of the second-level menu is derived from the parent class of the first-level menu, so the functions of the second-level menu such as ToolStripDropDownButton can also be added to the first-level menu
  • Derivation : Has sub-level menu function classes - ToolStripDropDownButton, ToolStripMenuItem, ToolStripSplitButton
  • Function : Parent class with child menu function: ToolStripDropDown, ToolStripDropDownButton or ToolStripMenuItem control, display the basic functions of the ToolStripSplitButton control. Similar to ToolStripItem providing no child menu

3. Case

1. Dynamic declaration menu (of course, it can be added by configuration)

private ToolStrip toolStrip1; //菜单栏
private ToolStripContainer toolStripContainer1; //面板,放于顶部存放toolStrip1
private ToolStripDropDown dropDown; //按扭ToolStripDropDownButton弹出来的子菜单容器,二级菜单
private ToolStripDropDown dropDown2; //按扭ToolStripDropDownButton弹出来的子菜单容器,三级菜单

2. Add sub-items to the dynamic menu (similarly, you can add them by configuration)

     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. Traverse the first-level menu

 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. Traversing the second level and above menus

/// <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. The configuration form is as follows

insert image description here

4. The running results are as follows

insert image description here
No matter how much and how much, you can traverse successfully

Four. Summary

1. Type analysis

  • It is really lazy, here is a brief description without drawing a class diagram.
  • Container control class: ToolStrip, ToolStripDropDown, the former is the container of the entire menu bar (that is, the first-level menu bar container), the latter is the second-level and above menu container, and the former is the parent class of the latter. They have the common attribute Items, which stores the menu function class
  • Menu function class: mainly divided into two categories, one class does not have sub-level menus, such as: ToolStripButton, ToolStripControlHost, ToolStripLabel, ToolStripSeparator, its parent class is ToolStripItem, and the other class has its own children, such as ToolStripDropDownButton, ToolStripMenuItem, ToolStripSplitButton , whose parent class is ToolStripDropDownItem, they have the same attribute: DropDown, which store their own child menu containers.
  • Menu function class collection class: ToolStripItemCollection, this class is the type of the property Items of the container ToolStrip and ToolStripDropDown. It has an attribute A list of ToolStripItem[] type, which has an overload of the Add method, which is used to add the ToolStripItem type to the attribute A list, and defines an indexer to obtain the value of the attribute A list

2. The beauty of polymorphism

  • If we let us set up the ToolStrip control by ourselves, we must first make clear the requirements: buttons with many functions can be added, and some buttons have their own submenus. Similarly, submenus can also add the same kind of buttons, wireless matryoshka...
  • Starting from the container, it is recommended to have two kinds of containers, because the container can be seen by the control. Of course, the first-level container is a common horizontal row on the top menu bar, and the second-level and above containers are the pop-up Window-style arrangement, and the two containers have too many similarities, such as Items, which have attributes of the ToolStripItemCollection type, etc., so use polymorphism to write their common points into the same parent class, so you can understand ToolStripItem and ToolStripDropDownItem and their
    derivatives class, and ToolStripItem is the parent class of ToolStripDropDownItem, it can be understood that ToolStripDropDownItem is a special ToolStripItem, because it not only inherits the properties of ToolStripItem, but also has its own properties (DropDown)

3. Recursive setting

There are two traversals here, mainly considering the particularity of the first-level menu. Of course, ToolStrip itself is the parent class of ToolStripDropDown, and it can be traversed completely with one recursion. Interested students can try it out by themselves.

Note:
Reprinting this article needs to indicate the source!
Gu Zipeng: [email protected]

Guess you like

Origin blog.csdn.net/a1062484747/article/details/130017050