Ryan
Ryan

Reputation: 7959

How to manage a WinForm with tons of variable sets of input text fields?

I'm writing a C# Form for adding various entries into a database. There are about 15 different types of entries. All entry types share several common properties such as name, date, comments, etc. Also, all entry types have about 10 other unique-to-that-type properties.

In an effort to avoid writing 15 separate forms, one for each entry type, I am attempting to do this all on one form.

Currently, I am using a tab control and putting all of the unique input fields for the properties of each entry type onto a tab control page for that type. I just change the tab control page to the selected entry type to display that entry type's input fields. I read from those fields when saving the entry to the database.

I figure there must be a better way to do this. This is actually a little slow on my machine, and my machine has a quad-core processor! Visual studio is even a little sluggish while saving this form.

Are there any decent ways of creating these dynamic field sets at run-time?

Upvotes: 2

Views: 312

Answers (6)

Ryan
Ryan

Reputation: 7959

Alright, I think I have come up with a very elegant solution to this.

I discovered a very nifty control called the FlowLayoutPanel. This will automatically align all controls inside of it to the top-left, by default. The controls will auto-adjust when other controls are hidden or made visible. This is exactly what I was searching for.

I ran into issues, though, when I wanted to add both a Label and a TextEdit, for example. The Label and TextEdit both followed the flow, instead of the Label being on top of the TextEdit. There is a property for the Label that you can toggle on or off as to whether or not it should break the flow. I pursued this until it became apparent that it was going to be painful hiding and unhiding both the Label, and the TextEdit that the Label goes to, when I needed to toggle the various form states. (each state has to show or hide a different selection of the available input fields)

So, what I did here was create a generic custom control that has two Panels on it, both docked so they re-size nicely. The top Panel contains the Label control. In this base custom control with the Label, I created a public property for editing the Label's text. Next, to accommodate for various form input types, I created multiple custom controls that inherit from the base control with the Label. On these child controls, I put the input fields needed - TextEdit, ComboEdit, DateEdit, etc. Each child control has public properties for getting and setting the values in their respective input controls.

Now, it's as simple as adding however many different custom "LabeledField" controls that I made to the FlowLayoutPanel and they adjust as intended. Now, I can show or hide only the ones I need and I am not repeating any code across all the varying form states! This is similar to Denis Biondic's suggestion, except that I am not using a Form but instead a custom control. I don't think I'd personally recommend using a Form for this, which is why I'm providing my own answer.

Upvotes: 0

Tigran
Tigran

Reputation: 62266

In addition to posts here I would add a suggession: I find for this kind of applications where you have to have a lot of fields on UI to let to user to insert them, that doesn't mean that you need to provide that fields to user.

What I mean, is, if it possible in your case cause it's not clear from post, just do not show all fields of every entity, but have it, for example in expandable GroupBox (just an example), and show actually only if user wants to fill it with some data, if not just leave it with default data, who cares...

This, if it is possible in your specific project, will save a lot of UI space on the screen, but what is more important will free the user from frustration to see all that "mess" on the screen and concentrate on things important to him in that precise moment.

Hope I express myself clearly.

Regards.

Upvotes: 0

LarsTech
LarsTech

Reputation: 81620

I find putting all of those controls in each of those 15 tabs a bit cumbersome-- it's hard to maintain and then you have one form with so much code it becomes hard to navigate.

It's probably better to create 15 sub-forms (borderless, TopLevel = false, dock = fill) and then you load the sub-form as you select a tab:

private subform _subForm1 = null;
private subform _subForm2 = null;

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
  if (e.TabPage.Name == tabPage1.Name)
  {
    if (_subForm1 == null)
    {
      _subForm1 = new subform();
      tabPage1.Controls.Add(_subForm1);
      _subForm1.Show();
    }
  }
  else if (e.TabPage.Name == tabPage2.Name)
  {
    if (_subForm2 == null)
    {
      _subForm2 = new subform();
      tabPage2.Controls.Add(_subForm2);
      _subForm2.Show();
    }
  }

For the common fields shared by these forms, I would create a usercontrol.

Upvotes: 1

Schroedingers Cat
Schroedingers Cat

Reputation: 3139

I would suggest looking at lazy loading the other tabs, possibly by an ajax call when the tab is clicked, to return the entire html for the tab. A similar ajaxed approach to saving the data would also be good. You might even want to do this for the first tab.

This is not trivial, but should mean that the html loaded is significantly smaller, however, you do need to manage the loading and displaying.

Upvotes: -1

Denis Biondic
Denis Biondic

Reputation: 8201

Maybe I don't understand you fully, but have you tried Visual Inheritence concept. Create a form with all shared functionalities you can extract, and have your child forms (forms that inherit the shared form) implmenent the specifics. This can't be slow, I use it all the time.

Also, WinForms will really have only small benefits from your machine hardware, cause it is and old GDI+ technology that isn't optimized at all for running on modern machines (not that it is slow, but don't expect anything extreme, it is not meant for graphic intensive things, it doesn't even use the graphic card for that matter, processor most of the time).

Upvotes: 2

Ovais Khatri
Ovais Khatri

Reputation: 3211

you can use a simple gridview with two columns and fill on column with the labels and keep them readonly, while another column for input.

Upvotes: 0

Related Questions