I have created two separate UserControls and (depending on which RadioButton is selected) I would like one or the other to be displayed.
Right now, I simply dragged one instance of each UserControl onto the form and placed one on top of another (setting one .Visible = false;).
This is OK, but I was wondering if there was a better or more appropriate way to do this?
That's perfectly reasonable.
If you're concerned about keeping around resources you're no longer using, you can add a Panel and add or remove the control from there.
E.g.
try
{
panel.SuspendLayout();
panel.Controls.Remove(userControl1);
panel.Controls.Add(userControl2);
}
finally
{
panel.ResumeLayout();
}
If the user controls do things like connect to data sources, you might want to actually dispose and recreate them. Really depends on how complex the controls are. If they're just capturing a few properties, your current solution is fine.
Related
I'm creating a Windows 10 Universal app, there are two panels in my main page.
In tablet/desktop mode, both are visible at the same time (just two simple Grids, one fills the left side and the other one fills the right side)
However, in phone mode, there's a pivot and user can swipe between panels.
(I could use SplitView and hamburger menus which work easily in both Tablet/Desktop and Phone modes, but a pivot makes more sense in my case)
So, What I currently did is, I have two instances of each panel. PhonePanel1 and PhonePanel2 are two grids inside two pages of my pivot control, and TabletPanel1 and TabletPanel2 are two grids which can be shown side by side. and I use AdaptiveTriggers to detect page width and switch between these two view methods.
However, having two instances of each panel is not a good approach, because those are showing basically the same content.
Is there any better approach to do this? Maybe changing Grid's parent when triggers are changing view mode? or something better?
The only way to change the parent that I can think of is to write some code behind that will render them in the new location. A suitable solution may be to defer the loading of the controls until they are needed.
x:DeferLoadStrategy=”Lazy“
If you add this property to your controls that are duplicated, they will only be loaded when required. So on a phone the PC/Tablet view should never be loaded, unless the user is running in Continuum on an external display.
On a PC you may still end up with both loaded (If the user resizes the window) - On a PC there are usually more resources so it's less of a problem there in most cases.
I looked into the code behind approach to move the controls to a different parent and I think honestly it's premature to do that when it might not even improve performance.
I have gone for the Defer Load Strategy property and found performance to be fine, and it requires very little code. My duplicate controls are sharing the same ViewModel so I pretty much just added the property to ensure resources are only used when essential.
There is nothing wrong in your approach. To reduce memory usage, when adaptive trigger happens for example on the phone, set TabletPanel1 and TabletPanel2 visibility to collapsed.
If all panels use the same datacontext then leave it as is, if not set datacontext for collapsed controls to null.
You could create each of your panels as user controls then you've only need to define the contents once but each control could be included in each of the layouts you want.
I currently am working on a WinForm project in which there are several different tabs. Within each tab there are various controls such as buttons, sub-tabs, text-boxes, ect...
I need to consolidate the overall application which involves taking certain controls from one tab and moving them to another. When I first tried doing so, I simply copy and pasted the controls. As you can imagine this didn't work due to the fact that I didn't move the properties with the controls, I really just created NEW ones on a different tab. Therefore when I complied the code, nothing worked because there was no code assigned to the new controls.
When I tried it again, this time I CUT and paste which also maintains the same properties as the old controls (specifically the reference name in the code), so as far as I can tell, the code should identify the controls by name, and apply the same actions. However, when I compile the code, the application successfully builds but the controls do not perform any actions.
At this point I am not sure what to do...
Use the Document Outline.
View... Other Windows... Document Outline.
Select the required component and drag it from one tab page to the other in the tree control. I did this and the actions are preserved in the new tab page.
Drag the item out of the tab control and onto the form itself. Change to the other tab. Then drag the item into that tab. It is essentially 2 drag moves, but since you do not ever cut, all code linking is maintained. If your tab control takes up the entire form, simply make it smaller while you do the preceding steps and then make it large again when you are done.
When you "cut" the controls, you sever the connections between the controls and their respective events. When you "paste" them again, they're not hooked up to the events anymore, so they don't appear to do anything.
The "event" methods should still be present in your code, but you'll have to manually go through and subscribe each event to each control again (via the Properties window).
Alternatively, revert those changes, then open the .Designer.cs file and look for something like this:
this.tabPage1.Controls.Add(this.dataGridView1);
Which (for example) places dataGridView1 inside tabPage1.
If you wanted to move the DataGridView to another TabPage, you could just change this.tabPage1 in the above code to this.tabPage2.
this.tabPage2.Controls.Add(this.dataGridView1);
Then you can flip back over to the designer view and move the control around to wherever you want it within the TabPage.
I just tested it. What is happening when you cut and paste your controls, you losing the wiring of the events. What you need to do after cut and paste is to go to control properties-events, find the event in question and on the right, select a method that you want to handle that event.
This will cut them from the first TabPage and paste them on the second, i think you can do this as often as you want. And with a small change you can make it a truly copy.
hope it helps
private void ControlsToTabPage(TabPage from, TabPage to)
{
Control[] ctrlArray = new Control[from.Controls.Count];
from.Controls.CopyTo(ctrlArray, 0);
to.Controls.AddRange(ctrlArray);
}
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've got windows form app I'm developing, and my client wants a TreeView on the left with nodes that when clicked allow their users to work in detail screens on the right. The simplest approach was to create panels which are disabled until the appropriate node is clicked. However, this app is growing and way too much of it is living in the main form.
I'm wondering if it is possible to have one form per node that will open and expand into the detail area on the right, and then close when I am done with it. That way I don't have a single monolithic form, however I am not sure of how to go about that.
Anybody have any insight into how to do something like that?
Thanks.
You should try using UserControls.
Basically, each UserControl is a form (more or less) that you can add to your main form just like you would any other control.
I would inherit from Panel for each page, attach an instance of each Panel-derived object to the Tag property of each TreeView node, and display that (Dock=Fill) when a node is selected.
You can use split controls and load the forms right side but needs to arrange it correctly. As #codethis mentioned, usercontrol is best enough to handle these as their code is written separately. Just you need to pass the parameter (from node selection).
You may need to multiple user controls and place them in your form according to your screen changes.
Here's a screenshot of my application:
Basically, depending on what option is selected I'd like to show another 'content' which can be a buttons, or forms or whatever.
What would be the best choice for this? Using MDI? I'm really new to this type of thing.
This scenario lends itself well to tab pages, as you'd find on a TabControl.
However, since you already have a mechanism for switching between the content, you might prefer to create a series of Panels whose Dock property is set to DockStyle.Fill. When the user clicks the appropriate heading, you simply need to show the appropriate panel and call BringToFront() on it. This is essentially what the tab control does internally, anyway.
Don't forget to use SuspendLayout() and ResumeLayout() appropriately to reduce flicker, which can be a huge problem in WinForms applications, especially when there are lots of controls.
You can position a TabControl where the buttons are not visible and control it from your buttons.