How can I dynamically add a user control to my form and making sure it is aligned properly? In other words, what's the easiest way to control how things are aligned (centered, vertically, horizontally, etc.) when adding it dynamically to my form?
I found the following that works:
http://www.vcskicks.com/align-user-interface.php
One option if you want to explicitly define the location of each new control:
lets say you have a list of objects that you want to create controls for but in different instances you may have a different number of objects in the list. You can loop over the list, instantiating a new control for each item, and placing that control on the form or in another control(like a layout panel) and then explicitly assign the properties of the new control, specifically the location.
Say you want all of your dynamically added controls to be lined up vertically;
assign newcontrol.Location = new System.Drawing.Point(550, offset);
and increment offset by the desired spacing each time you go through the loop.
Related
I have created a FlowLayoutPanel where labels are added dynamically, the label data is taken from a datagridview. Is it possible to sort those labels using a Date column from the datagridview?
A flow layout panel will keep it's child controls in the order that they are added to it.
This means that you can't sort the controls on it.
Your only options are either to remove all the labels and add then in a different order, or to use a regular panel and then sort the existing label by changing the location property of all the labels.
The first option is, of course, much easier.
It is possible to order items of any container using the SetChildIndex method.
Here is an example of how to move an item up one place:
myControl.Parent.Controls.SetChildIndex(
myControl, myControl.Parent.Controls.GetChildIndex(myControl) - 1)
Is there a simple way to change the order in which controls are displayed within a panel? I do not mean Z-Index. I mean explicitly setting the 'flow order'. Thank you.
The StackPanel and the Grid use a Children property of type UIElementCollection
By using Remove(At) and Insert you could change the order of the elements in the collection.
After that it depends on the Panel (Grid, Stack, Dock, ...) whether or not, and if how, it uses this order.
Some Panels, such as the Grid, also use attached properties (Grid.Column, Dock.Top) to position elements so there is no single way of re-ordering for all panels.
If the elements are added dynamically through data binding, re-ordering the data items in their collection might cause the Panel to display the controls in a different order.
I have data for several days. I want to plot that data, one day in one tab page. The tab page can change dynamically corresponding with the number of the day.
Previously, I always make a static page in the design mode. I use ZedGraph control to plot the data. I decided how many pages that I need. Then it means the number of pages is static.
Now, I need more dynamically. I want the number of tab pages can change dynamically. Each page has similar controls inside it. How to do that? I have no clue about it.
First you create a new class of type UserControl. These are meant to act as containers for controls. Then you put everything on it you need in your typical tabpage including the ZedGraph control..
Also write your logic there.
Now, when you need another page you create one and add a new instance of the UC class you have created.
You should think a little about dependencies with the rest of you application, including the deleting of the pages; a page controller class comes to mind that can handle these things, if necessary.
You could also subclass a tabpage but going the UC way gives go an additional layer of independency; you could place the same UC on a form or inside a container control..
I am looking to create a windows form. This form is to display groups of data separately and I was aiming to do so in the same form window rather than have multiple windows open.
For example each group of data is defined by a Job#. A user will want to review X different Job#'s at a time (Range would usually be 1-5, but could be more). I would like to have 4 dataGridViews for each Job# plus various identifying and summed data in text boxes. Initial Example Concept
I was looking into using TabPages/Tab Controls. My initial idea was to have a user click the different tabs to view the data for those jobs that they have pre-selected. However these tabs don't seem to behave like classes from what I can see. Is there perhaps a better way to go about this or some way to have the tabs act like classes? So that each tab has a Job TextBox, 4 Different DataGridViews, etc. So that I can easily create and display any number of jobs?
For example each Tab would have 4 dataGridViews, maybe 8 Text Boxes, Standardized Labels and a Standardized layout.
So would using tabs be a good idea? Using some other WinForm control?
There are at least 2 solutions here:
Create a custom Panel holding all the controls you want (TextBox, DataGridView, ...), design it so that it looks best to you. Then add each of that Panel to each of TabPage of your TabControl.
Create a new custom TabPage and add the custom TabPage to your TabControl.TabPages instead of the standard TabPage.
I think the second approach can be done if you can initialize everything using code (not by drag-n-drop) because to get the drag-n-drop supported, you may need to write a custom TabControl. So the first approach is feasible and OK. You can replace the Panel by a Form, set the Form.TopLevel = false, you can add that form to any container control. Using Form, you can benefit the easiness of drag-n-drop to design and organize your controls.
Here is a little of code which may help you figure out:
public class TabPageClient : Form {
public TabPageClient(){
InitializeComponent();
Dock = DockStyle.Fill;
TopLevel = false;
FormBorderStyle = FormBorderStyle.None;
}
//.... other code
//I think this is important
//You should define some Properties and methods to control the data flowing into and out from your TabPageClient.
//You can also support some method to add/remove the controls dynamically.
}
Take the drag-n-drop requirement into account, I think using UserControl may be better:
public class TabPageClient : UserControl {
public TabPageClient(){
InitializeComponent();
Dock = DockStyle.Fill;
}
}
For UserControl, you should place the class in a separate *.cs file, compile your project and then you can see it in the ToolBox window (at the very top). Just drag and drop it like as other controls.
Personally, I prefer grid-detail views. Something we make heavy use of in our software. The form has a SplitContainer in vertical alignment.
In the top panel, you add a list of some kind (ListBox, ListView, DataGridView...any control into which you can load a list and then react to selection).
In the bottom panel, you have yet more options. Simplistically, you could use a TableLayoutPanel and then setup rows/columns to provide whatever arrangement of embedded controls you like, such as your array of grids to display data. I suppose in keeping with your model, you'd have a single ColumnStyle and four (4) RowStyles. Then in each row, add a grid.
This way, you keep it all in one place...one "screen", if you like (no tabs to flip through). You react to the selection in the list to decide what data to display in the grids. You then just need a bit of code (a class I would hope) that interfaces between the class(es) that provide the data, and the form controls that display it (the grids).
An additional benefit here is that with the list presentation, you can have a lot more than five (5) jobs in play at any one time. In fact, with scrolling, as many as you like (not limited to the number of tabs before the display goes to pot).
Also, you would be re-using the grids. Simply refreshing the displayed data for the list item selected. You could even pre-load and cache it all if freshness is not an issue.
Also consider binding directly to data source if that's an option.
I am using a Panel to hold a list of controls (user-defined). The way that I add the panels, I am setting the location of the control based on the Panel.Controls.Count before I add it to the panel.
comRec.Location = new Point(comRec.Location.X, panel1.Controls.Count * 25);
panel1.Controls.Add(comRec);
Now, this works nicely and looks exactly the way that I want it to. However, once we reach the limit on the window, the AutoScroll enables (which I do want). Now, if the user were to scroll to the bottom of the Panel, this ultimately changes the location of every control in the panel. Instead of my first comRec.Location being (0,0), it is something like (0,-219). So now, when the user adds another comRec object, it creates a HUGE gap between the objects.
My question is this, what is the best way to account for the changes of the location with the scrollbar and still using my adding system. I am assuming that will have to do something with checking the value of the scrollbar and using it to determine the location.
Also, is there a BETTER way to display a list of controls? Should I be using a Panel?
Look at the FlowLayoutPanel control, it's exactly what you what.
You could add an additional panel into the hierarchy:
Outer panel (scrollable)
Inner panel (not scrollable, resize it whenever you add a control)
User Defined Control 1
User Defined Control 2
User Defined Control 3
User Defined Control 4
...
This way, your additional controls' locations would be relative to their direct parent, the non-scrolling panel.
If you add several controls, try to suspend the layout of the panel while adding the controls:
panel1.SuspendLayout();
// Add controls ...
panel1.ResumeLayout();
This helped me in a similar situation where the user could change dynamically the visibility of existing controls.