How to append dynamically created Windows Forms controls? - c#

While I can easily accomplish in ASP.NET using AddAt(), I am trying to do the same thing in Windows Forms.
I have a panel, and while I can do a pnlMyPanel.Controls.Add(ctl) ... it always inserts it in the 0 position, when I would rather have it appended to the end, or pnlMyPanel.Controls.Count.
Am I overlooking a method or am I going to have to do something else?

It depends how your controls are being laid out.
I assume that all of the controls in the panel have their Dock property set. If so, call BringToFront, SendToBack, or SetChildIndex on the new control after adding it to the panel.
If not, set the Top and Left properties (or the Location property) of the new control.

AddAt functionality can be implemented by a combination of Add and SetChildIndex methods.
You can use
SetChildIndex Method
to reorder the index of the child control after adding the child control.
When SetChildIndex is called, the
Control referred to by the child
parameter is moved to the position
specified by newIndex and the other
Control references in the
Control..::.ControlCollection are
reordered to accommodate the move. The
control with an index value of zero is
at the top of the z-order, and higher
numbers are closer to the bottom.

Related

Get index of control located in e-th coordinates

I have a flowLayoutPanel on my form. I have some controls there which can be dragged and dropped . What I need is to get the index of the control, which is located on mouse position, for example if mouse is on the first widget, I have to get 0. Please show me some way how can I do it.
Thanks
EDIT
Frogot to upload the photo ,sorry
You will need to iterate through the controls in the flowLayoutPanel.Controls collection to find which control is under the mouse. Then iterate through the list again to find how many controls are above/equal height and to the left of the control in question.
I don't think you can avoid the 2 iterations, as the ordering of the collection is not tied to physical position.
I realize this is a 5-year old question, but since this question and answer still pop up in Google, I feel compelled to provide a genuine answer.
The FlowLayoutPanel class provides a method called GetChildAtPoint which takes a client-relative location and returns the control at that position (if the position is the mouse location relative to the FlowLayoutPanel window, then that identifies the control under the cursor). Worse case, then, you only have one linear search iteration through the FlowLayoutPanel's children to match objects (if in fact, your objective is to get the actual index instead of finding the index to look up the control; if finding the control is what you actually want, you are already done).
In my particular application, I needed to track things easily in a drag-drop scenario where a control could only be dragged within a range of related controls. So I used the "Tag" property to populate the index into the control itself as I was populating the panel (actually I stored a reference to the base class of my child control wrappers, and maintained the index in a base-class Property that I could query after casting the Tag to the base class, but I digress. The reference allowed me to get all kinds of cool information about the window under the cursor for appropriate display and/or manipulation in addition to maintaining the parent index).

Drawing Custom Control above all other controls (previously added)

I have a UserControl that adds other UserControls, but I want the "latest" control added to be topmost so it's above the others. Because the controls should be overlapping eachother. Like a card game. So I add 5 controls, the first one should have the least priority the latest the most priority - most visible.
Any ideas?
Or do I have to override the Paint method for the "container" control? And Control.CreateGraphics() and draw it?
Consider BringToFront and SendToBack methods of the Control class.
Check out answers to these questions too
How to set Z-order of a Control using WinForms
Bring Winforms control to front
Just use userControl1.BringToFront() when you add the new control.
Note however, that won't prevent the user from "tabbing" into the controls that are underneath it. For that, you need to disable or make invisible the other controls.
In Windows Forms, the order in which controls are added to their parents' Controls collection determines the order of their rendering.
This means that either you handle the addition of child controls in code and use the appropriate insert positions, or you move the controls around in the designer (which, unfortunately, often means dangerous hand edits to the *.Designer.cs file).
I recommend that you go for the first approach, which is the only feasible method for larger WinForms projects anyway, and make the control insertion logic explicit in your code. The good news, by the way, is that there is no need to tinker with paint handlers, so your worry about hacks like using CreateGraphics() is unjustified and dispelled :)

Prevent Child Components when Overlapping Panel

I have a WinForms application which has two panels which individually contain a usercontrol component (one in each panel). How ever, because both panels are the same size and in the same location, the top most panel becomes a child of the other panel. I want to be able to hide one panel and then show the other panel:
this.panel1.visibile = false;
this.panel2.visibile = true;
But when I hide panel1, the second panel is hidden as well.
How can I make panel2 a non-child of panel1?
I like to keep things simple because I'm new to C# Programming.
This is a common accident in the designer. Dropping the second panel on top of the first one will make it a child of the first panel. Two basic strategies to fix this:
View + Other Windows + Document Outline. Click the second panel in the list and drag it to the form. You'll need to fix up the Location property by hand by typing its value in the Property window.
Keep the upper left corner of the second panel just a bit to the left or top of the first panel. Put it in the right place in the form's constructor by assigning its Location property after the InitializeComponent() call.
Check this answer for a control that works well at design time and lets you easily flip panels at runtime.
The designer will do this automatically because it assumes that when you drag one control over another, you want to make it a child of that control.
What I usually do to get around this is to create the control in a different place on the form, and then use the properties to manually match the positions of sizes of the two controls.

Winforms: FlowLayoutPanel with Docking

This is in winforms. I am creating a User control that is basically a FlowlayoutControl filled with other User Controls. I need each of the controls added to be docked to the top of the previous (from left to right). Unfortunately it looks like the flowlayoutcontrol ignores any of the docking properties. Is there any way to dock the controls inside there? I need it to fill the item from left to right, but the items should be laid out like a list view. Theres really no code i can provide due to the fact that its a matter of figuring out what approach to take.
Getting the FlowLayoutPanel to dock right is tricky. From the original question, you want something like a list view. It's important to know that ONE of the items in your list (the widest one) defines a "virtual column" in the FlowLayoutPanel. The rest of the items will follow it. You can prove this in the VS designer by dragging one of the items to the right. The 'virtual column' will follow it, and if your other items are anchored they will follow the virtual column.
Note that you can't anchor the control that is defining the column. It has nothing to anchor to and strange things will happen.
Do do all this programatically, handle the Layout event on your FlowLayoutPanel and put code similar to the code below. It's important that in the designer all the items in your list are not docked and and have their anchoring set to 'none'. I spent a day on this yesterday and doing that in the designer is what made the code below work.
flowLayoutPanel.Controls[0].Dock = DockStyle.None;
flowLayoutPanel.Controls[0].Width = flowLayoutPanel.DisplayRectangle.Width - lowLayoutPanel.Controls[0].Margin.Horizontal;
for (int i = 1; i < flowLayoutPanel.Controls.Count; i++)
{
flowLayoutPanel.Controls[i].Dock = DockStyle.Top;
}
FlowLayoutPanel.FlowDirection Property indicates the flow direction of the FlowLayoutPanel control.
FlowLayoutPanel.WrapContents Property indicates whether the FlowLayoutPanel control should wrap its contents or let the contents be clipped.
The docking properties of the FlowLayoutPanel are for the panel itself (like if you wanted the FlowLayoutPanel docked to the left of the form, etc.), not the container of controls inside of it.
Try playing with the DefaultPadding and DefaultMargin properties, these apply to the spacing of the controls it contains

Show and Hide UserControls (BringToFront/SendToBack)

I'm working on a "tricky" UI. Part of what I need to do is easily show and hide various UserControls. Generally one control will occupy the entire main window when needed, the other's will hide.
In WinForms I used to simply use SendToBack and BringToFront and easily showed the control I wanted to show. Now I have no clue. Played around with zorder but that didn't seem to work.
I'm thinking maybe put all the controls I want on the main window, then pro-grammatically resize them and remove the unused ones... or something.
Any ideas?
You should set the Visibility property to Collapsed, Hidden or Visbible depending on whether you want the controls removed, hidden or shown.
As #AresAvatar points out Collapsed removes the control completely so it takes up no space, this means that other controls may move around the container. If the position of elements is important then using Hidden will be the better option.
UIElement.Visibility Property on MSDN
Visibility Enumeration on MSDN

Categories