user control that other developers can add control

2019-08-12 03:16发布

问题:

hi all and sorry for the confusing title... can't find the right words yet. just out of curiosity, I am playing with c# user control, I created a control that is built from a panel, a textbox that is being used as a filter, and some labels / buttons/ etc... that are being filtered. when ever you change the text of the textbox, all the controls on the panel are visible / invisible depending if their Text property contains the Text of the textbox. very simple.

but I want this user control to be such that the user that uses it can drop more labels or controls to it and they will behave the same, I can't figure out how to do that..

when I am editing the control (adding controls to it), it works as expected and the new controls behave as the old ones without code modifications, but only when I am editing the user control and not when using it.

when I am dragging the user control to a form, I can not add controls to it... when I try to add a label to the control - it is just added to the form and not to the control and therefore the text box is not influencing the added label. what should I do if I want to be able to add the control to a form and then add some controls to the control?

I will be happy for some pointers. here is the relevant code:

private void textBox1_TextChanged(object sender, EventArgs e)
    {
        foreach (Control c in panel1.Controls)
        {
            if (c.Text.Contains(textBox1.Text))
            {
                c.Visible = true;
            }
            else
            {
                c.Visible = false;
            }
        }
    }

edit - pictures added.

as you can see - i typed 1 in the filter text box and all the controls except button1 are now invisible - and of course the bad behaving label.

Thanks, Jim.

回答1:

You describe one of the reasons why I almost never use UserControls. Anything that isn't done to the original UC must be done in code..

You can instead make it a class that is not a UserControl, ie make it a simple subclass of Panel (or FlowLayoutPanel as I do here merely for convenience, while dropping stuff on it during my tests).

class FilterPanel : FlowLayoutPanel
{
    TextBox tb_filterBox { get; set; }
    Label st_filterLabel { get; set; }
    public FilterPanel()
    {
        st_filterLabel = new Label();
        st_filterLabel.Text = "Filter:";
        this.Controls.Add(st_filterLabel);
        tb_filterBox = new TextBox();
        this.Controls.Add(tb_filterBox);
        // st_filterLabel.Location = new Point(10, 10);  // not needed for a FLP
        // tb_filterBox.Location = new Point(100, 10);   // use it for a Panel!

        tb_filterBox.TextChanged += tb_filterBox_TextChanged;
    }

    void tb_filterBox_TextChanged(object sender, EventArgs e)
    {
        foreach(Control ctl in this.Controls)
        {
            if (ctl != tb_filterBox && ctl != st_filterLabel)
                ctl.Visible = ctl.Text.Contains(tb_filterBox.Text);
        }
    }
}

Now after placing it on a form (or whatever) you (or whoever) can drop Controls onto it in the designer and they'll be part of its Controls collection, just like you want it and will behave as expected..

Two notes on subclassing Controls:

  • If you break one during developement, the Form(s) using it will be broken, too, until you fix the problem. So take a little extra care!

  • For the Designer to display the Control it always needs to have one parameterless constructor, like the one above. Even if you prefer to have the ability to hand in parameters, one parameterless constructor must still be there or the designer will get into trouble!



回答2:

This problem can be solved easily by following the guidelines in https://support.microsoft.com/en-us/kb/813450 which decribes step by step How to make a UserControl object acts as a control container design-time by using Visual C#

In order to modify the user control as a design time control container add the following code to the Declarations section:

using System.ComponentModel.Design;

Apply the System.ComponentModel.DesignerAttribute attribute to the control as follows:

[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] 
public class UserControl1 : System.Windows.Forms.UserControl
{
          ...
}

Then build the solution. the control will appear as usual in the Toolbox and can be added to forms. Additional controls such as buttone , text boxes etc.. can be added to the control as required.