Custom GroupBox control with other controls inside - c#

I didn't like any available solutions so I started to make my own wizard interface. I use a GroupBox for each step of the wizard but since every step (every GroupBox) must have the same structure and style, I decided to use custom controls.
Now I need a custom GroupBox which has these elements:
A FlowLayoutPanel so the developer can put desired controls in it using the designer. (For example two TextBox controls so the user can enter a username and a password.)
A Label in that FlowLayoutPanel to describe the step.
A Button to go back.
Another FlowLayoutPanel that user can put custom buttons in.
Here is a preview:
Problem #1
When I create a new UserControl and make it inherit the GroupBox, I can't get a GroupBox that I can put and position stuff in it. All I see in the designer is this message:
Problem #2
Since I couldn't make it inherit GroupBox like I wanted it to, I tried doing it by putting a GroupBox in the custom UserControl. (I don't want this. I just did this so I could provide some screenshots.) After I did that, I had to EnableDesignMode on the FlowLayoutPanels so the developer could add controls in them by using the designer. The problem is that they also became movable and resizable (I don't want this. They are anchored properly and they should not be moved nor resized.) and when you try to move them you get "Object reference not set to an instance of an object." which is making it uglier:
Problem #3
I want elements in the main FlowLayoutPanel to be centered. To do this, I had to put a control (the description label) and resize it to the width of the FlowLayoutPanel so the controls after it would be centered. (Messy workaround if you ask me. Doing this with TableLayoutPanel looked easier but their cells can only hold one element. You can add a Panel to make the cell hold more elements but then you lose centering.) The problem is that I have to set Anchor to None for every control I add. Can I hook something (like OnDesignerControlAdded???) to automatically set added control's Anchor to None?
All of your answers will help me build the open source project Magician on GitHub and many other open source projects powered by it. Thanks in advance for all of your efforts.

Quick answer for problem #1:
Design your groupbox (GroupBox1) on a Form or a UserControl (it doesn't matter).
Go to InitializeComponent() in the designer.cs file and copy all code related to the groupbox and its child controls.
Add a new Custom Control called CustomGroupBox to the project.
Change it to inherit from GroupBox:
public partial class CustomGroupBox : GroupBox
Paste all the copied code into the constructor of CustomGroupBox (or into a new method, which you call from the constructor after InitializeComponent(), if you want to be neat).
Remove all occurrences of this. from the pasted code. Replace all occurences of GroupBox1 with this.
For any child controls you want the developer to have access to, add a public property for that control.
E.g.
public FlowLayoutPanel FLP
{
get { return flowLayoutPanel1; }
}
And of course add your CustomDesigner
public class CustomGroupBoxDesigner : ControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
var c = component as CustomGroupBox;
EnableDesignMode(c.FLP, "FLP");
}
}
And apply the attribute
[Designer(typeof(CustomGroupBoxDesigner))]
public partial class CustomGroupBox : GroupBox

Related

Adding user control to GroupBox changes the user control's layout in WinForms

I have a WinForms application with a GroupBox in it. I have designed a user control which groups together a bunch of textboxes and other controls so that I can apply some custom logic to them. The user control looks like the following:
I want to place this user control within my GroupBox, however doing so ends up affecting the layout of the controls within my user control (see below).
As you can see, my textboxes are all spread out and resized from how I want them to be. If I place this control directly on the main form or in a Panel (not in the GroupBox) the layout is maintained, however the moment I place it in the GroupBox everything gets messed up. Is there a way to fix this problem?
The user control seems to have a different size in the two cases. Make sure it has the same size in the group box as when you place it directly on the form. If you have used a layouting control like a FlowLayoutPanel or a TableLayoutPanel, this might be of importance.
Also be aware that winforms controls inherit properties from their parent if they are not set explicitly. E.g., if you have not set the font property of the user control and its text boxes, those will be taken from the group box.
What ended up working for me was making a separate class MyGroupBox which extends GroupBox. The class is empty, but I converted the GroupBox on my form to this and placed the user control inside, which solved the problem.

Can't add inherited controls to GroupBox

Problem:
I cannot add any controls to a groupbox, if the controls were declared in another form.
Background Information:
I have MainForm which inherits from Form. It provides some functionality which I need in all of my forms, and have also added some custom controls/images which I need in all of the other forms.
With my forms, I reposition the controls/images from the MainForm to wherever I need and all is well.
But for some reason, I cannot move these same controls/images into existing GroupBoxes.
When I say can't I mean that VS is not letting me; when I drag the control over the groupbox, my mouse cursor switches to this "error" sign:
If I understand correctly then you have two or more level of inheritance hierarchy with your form, base class have the GroupBox you're trying to modify it in designer via derived form. Am I correct?
In that case VS prevents you to move control to groupbox which is declared in base class?
If yes, There are couple of things to check.
Check whether your groupbox is atleast protected, so that you can access it in derived class.
If yes, While you're dragging the control just right click the mouse(holding left button), then drop it into groupbox. It should work.
If you have troubles yet make the groupbox as protected internal and give a try.
Hope this helps

Losing styles when adding a User Control to a User Control

In my project, I am trying to add a button collection user control to an input based user control. The button uc is going to be added to numerous other controls. The problem that I've encountered is that the button uc is losing whatever css styles that I've attach to it, once it is added to the parent uc. Initially, I had a panel on the parent that would add the button uc when the page was loaded, then I would add the button uc to the panel:
(panel.controls.add(uc)
This did not work, the styling of the buttons were lost. Next, I tried to set the positioning to the button uc and add it directly to the form:
static void SetLocation(Usercontrol uc) {uc.Attributes.add("style","left:425px;top:420px;"); }
public void SetPage() { button = (uc)LoadControl(button.ascx); SetLocation(buttonuc); this.Controls.Add(buttonuc); }
But, this did not work either, it did not even locate the control properly. My style sheet is already added to the parent uc, and the button uc to be added has its style on that sheet. I don't want to have to manually add the buttons to each uc parent. Thank you for any help. I sure I'm just missing something obvious, but I've yet to come upon a similar issue in a search. Thank you.
In general it is good practice to keep your styles separate from the markup. This makes maintenance easier and it also saves yourself from searching for the reason one of your elements appears a pixel away from where you are expecting (for example... Similar issues can be exasperating).
Do you have the same issue if you set the CssClass attribute for your button(s) and set the styles in a css file for the class?

How to create a UserControl that you can drop other controls in it?

In WinForms, how can I create a UserControl that when I put on my form I can then add other controls inside by dragging them from the toolbox, the same way as with all containers controls (panels, group boxes, etc)? I've tried to add controls by dropping them in my control but then when I move my control the controls I added stay right where they are, which wouldn't happen if instead of my control I would use a Panel (the other controls would move with the panel).
Unlike a Panel control for example, a UserControl does not act as a container control once it is placed on another form. There is full design-time support while you are designing the UserControl itself, but its default behavior does not allow it to act as a constitutent control after it has been placed on another form. This is why you are unable to add other controls to it by dragging them from the toolbox.
In order to add this type of behavior to a UserControl, you need to add the DesignerAttribute to the definition of your custom UserControl class. For example:
using System.ComponentModel;
using System.ComponentModel.Design;
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public class MyUserControl : System.Windows.Forms.UserControl
{
//...your code here
}
(See the relevant MSDN article for further reading.)
If you want to implement full designer support for nested controls inside your UserControl, this is slightly more difficult. For a more comprehensive discussion, see this article on CodeProject.

WinForms designer: Add control and make it visible for the designer

I have a WinForms user control Host with a custom UI Editor.
Through that editor, a child control (Child) can be added to Host.
(The UI Editor creates Child and sets Child.Parent = Host)
Child is handled through a Holder<Child> helper class, which is set as Tag property of e.g. a ListViewItem.
The respective code - some of it, at least - gets added to the form: Holder is created, and set as Tag, which is enough to be created at runtime, too.
However, Child is not visible to the designer - it is displayed, but it can't be selected, nor does it occur in the drop down list with controls for the parent form.
I would like to:
see the Child control in the designer, so that I can modify properties
get notified if the control is removed
Is this possible?
[edit] Thanks all for your input. I've decided to skip the designer - I hoped to throw together something quickly, but apparently it requires more planning than I should allow myself to spend on it right now.
Usethis.Controls.Add(/*Instance of the child*/); on the host class. Then for the notification add event handler for the host's ControlRemoved event (this.ControlRemoved += new ControlEventHandler(Host_ControlRemoved);).
I can't say I fully understand exactly what you are trying to do.
If you are dealing with the problem of how a "child" Control of a UserControl placed on a Form at Design-Time can be made to function as a container onto which you can drag-and-drop other controls from the Toolbox : this CodeProject article by Henry Minute may be helpful : Designing Nested Controls. For example : you have a UserControl with a Panel inside it : an instance of the UserControl is placed on a Form : in the Design-time view of the Form : you want to be able to drag-drop controls onto the Panel in the UserControl and have them become child controls of the Panel : Henry's article will show you how to do that.
This from Microsoft : How to make a UserControl object acts as a control container design-time by using Visual C#
Perhaps might also be useful, although it seems like you already have this step accomplished.

Categories