Multiple classes in one form - c#

I'm using a TabControl in my form and it made me wonder. Right now I have only two tabs and I store procedures relating to both tabs (button handlers, &c.) in the code for the main form, so it looks like this:
public partial class MainForm : Form
{
// ----------TAB1-----------
tab1SearchButtonCLick() {...}
tab1AddButtonCLick() {...}
// ----------TAB2-----------
tab2EditButtonCLick() {...}
tab2SearchButtonCLick() {...}
tab2ClearButtonCLick() {...}
}
That's not a problem now with so little code, but it might be one in the future. Is this an acceptable way of doing this? What's the alternative? I believe I could put the tabs in their own classes, but I'm not sure how I'm going to do that exactly (there's lots of controls in each tab that I'd have to pass as arguments to constructors).

You should move the contents of each tab to a separate UserControl.
Each UserControl should be a self-contained unit that gets whatever data in needs from the main form and fires events to tell the main form to do things.

The tabs have event for a reason - the tab raises the event and doesn't want to handle it.
When you use the tabs (or other objects with events) you need to write the code that handles the event.
If you really want, you can write the class in separate files so you can keep your own logic in separate files.
If you'll notice a Form is generated as a partial class by Visual studio.
That's because the design code is generated in a separate file.
You can do that yourself by declaring other parts of the class as partial in other files.
More about partial in this link

Related

Why does VS2017 keep losing my derived controls?

In my app namespace = DRT, I'm creating control classes (e.g., button, textbox) that derive fron their corresponding Windows control classes, e.g.,
internal abstract class DRT_Button_Abstract : Button
{
....
}
internal class DRT_Button_CancelSearch : DRT_Button_Abstract
{
....
}
internal class DRT_Button_StartSearch : DRT_Button_Abstract
{
....
}
All together I currently have 13 derived classes that derive either from one of my abstracts or from a Windows control class. After a successful build, I see my control classes (e.g., DRT_Button_CancelSearch and DRT_Button_StartSearch) on the Toolbox and I successfully drop them onto my main form. All is fine for a while, but ultimately, I'll go to open the main form.cs [Design] (i.e., the UI designer) and it will show the error The variable '{control property name}' is either undeclared or was never assigned. for some combination of my controls.
When I examine the main form Designer.cs file, the expected code for all the controls is present EXCEPT for the expected new statement. They are not present in the main form Designer.cs file. For example, I expect to see this.drt_Button_CancelSearch = new DRT.DRT_Button_CancelSearch(); but its missing
I've tried ignoring the error, proceeding to the UI designer windows to re-apply the lost controls, but the problem just repeats with the newly applied control
What the heck is going on? Is there a way to recover from this situation?
This is most likely a problem of the Designer not being able to clear/reload its cache. There is not much you can do. In the past I:
closed and reopened all designers that have user controls
put all the controls in a separate project (in the same solution)
put all the controls in a separate solution/Visual Studio instance and set a proper reference to the controls' dll (or even nuget package)
With the first two options I have had varying success. Reopening the designer is not very convenient and doesn't work.
That last option is the best but also the most annoying because every adjustment requires a rebuild of the project and update of the reference/package.
Also make sure that all controls that you create have public default constructors and function well when this constructor is used.

c# multiple form with common items from basefrom

it's any way to inherit form from baseForm, f.e:
i have Baseform with menu and some button. Now I want to use it in my second form, but i would not copy-paste, but only:
public partial class Form1 : BaseForm
and now i have some problems, because compilator send me bugs:
Message 1 The designer could not be shown for this file because none
of the classes within it can be designed. The designer inspected the
following classes in the file:
dziedziczony --- The base class '_10widokow.BaseForm' could not be
loaded. Ensure the assembly has been referenced and that all projects
have been built.
Those errors probably due to your BaseForm either not being referenced, or you have other problems outside of the scope of the question.
Controls on a form are added by the InitialiazeComponents method generated by the Form graphical editor. You don't need to inherit to bring in a basic set of controls, but simply copy the generated code out to a common location.
Then call in the constructor of the forms in which you want the base controls.

Design Pattern /ListBox.Items.Count

i built an Winform application with Pcapdot.Net DLL's that take Pcap file and play all the file packets into the machine network card.
recently i have notice that all my main form (where all the buttons clicks\events) is a mess, i putt all the method inside those function and the code looks complicated and it's hard to understand so i started to rearrange this code.
because my application has Listbox where all the played files is inside i put all this play function inside the Play button for example: i have loop over my Listbox.Items.Count and inside i am handle this files. now i want to do something different and this is my question:
is it common way to define class that handle this Play function and from the main form every time that file added to my Listbox just fire up the event ControlAdded or after remove file ControlRemoved and put this files into my class who has List that hold this file ?
I think you would be better off rearranging it more like this (to separate the business logic from your UI):
Have a public method inside your Form class that returns an IEnumerable<string> which is the list of files, called something like SelectedFiles().
Make a public event property for the "Play" button which is raised when the user clicks the "Play" button, called something like PlayClicked.
Make a "controller" class which is responsible for creating and showing the form.
Your controller class would attach to the PlayClicked event. The controller's handler for PlayClicked would call the form's SelectedFiles() method to get the list of files, and would then do whatever it needs to do.
I would even consider wrapping the handling code for the selected files into another class called something like SelectedFileHandler and put the logic for handling the files into that, perhaps in a method called HandleFiles(IEnumerable<string> files).
Then the "controller" class would still be hooked up to the PlayClicked event, but it would use the SelectedFileHandler.HandleFiles() method to handle the files.
Does this make some sense to you? I could be misunderstanding what you're looking for.
I'm basically saying that you should use a Model View Controller or a Model View Presenter architecture.

Correct UserControl Usage?

I just started breaking up my GUI application into UserControls. I have a TabControl with a bunch of TagePages. Obviously my MainForm.cs file was filled up with tons of events and controls etc and it got very messy quick.
So a previous question gained me the insight of how to create a UserControl. I intend on creating a UserControl for each TabPage and I was wondering how I can interact with Components on the main form or other UserControls.
Here is an example of a TabPage that I have made using a UserControl, which needs to Enable or Disable a button depending which TabPage is currently selected. Is this proper usage or is there a better way?
public partial class TabDetails : UserControl
{
private RequestForm fRequestForm;
public TabDetails()
{
InitializeComponent();
}
public void CustomInitialization(RequestForm pRequestForm)
{
fRequestForm = pRequestForm;
pRequestForm.TabControl_Main.SelectedIndexChanged += SelectedTabIndexChanged;
}
private void SelectedTabIndexChanged(object pSender, EventArgs pEvents)
{
fRequestForm.Button_SubmitRequest.Enabled = fRequestForm.TabControl_Main.SelectedTab != fRequestForm.Tab_Details;
}
}
In the MainForm.cs constructor I call:
this.tab_Details1.CustomInitialization(this);
This doesn't look like a good use of a user control. The user control should not decide how things in the form should behave when something is changed in the user control. A user control should be unaware of its container and should operate in any container.
The user control should notify the form that something has changed without telling what's the internal implementation and the form should decide what to do.
Example:
A user control named "NameUserControl" consists of TitleComboBox, FirstNameTextBox and LastNameTextBox. The user control wants to notify when one of the values has changed.
Wrong Way:
Create events:
TitleComboBox - SelectedIndexChanged.
FirstNameTextBox, LastNameTextBox - TextChanged.
The problems here:
You expose the internal controls behavior. What will happen if you want to change the TitleComboBox to TextBox? You'll have to change the event name and implementation.
You expose the fact that you use exactly 3 different controls. What will happen if you want to use the same text box for first and last name? You'll have to delete one event and change the name of the other.
Good Way:
Create only a single event: NameChanged and expose 1 property of FullName or three different properties for the values.
Either way the form subscribe to the event and decide what to do next.
Another thing to think about: the more you add more functionality to your user control, you either make it less reusable or you make its code more complex. For example, if you add validation inside the user control, you'll find one day that you need it without validation, so you'll add a property "bool ValidateData" or it will be so complicated that you'll need to build another control. One way to solve that is to build very small user controls, but combine them in one or more bigger user controls that fit all your current needs.

Separate code in single Form [C#]

I've got a WinForm application with separate groupboxes and objects, but the code isn't sorted by groupbox and pretty messed up.
Can the code be split in 2 files or something with the objects on the same place?
EDIT:
this is my code:
how should i split it?
(i need everything with News and everything with Dir changed)
It sounds to me like you want to check out Partial Classes.
They allow you to split the code for a single class between multiple files.
You may find it easier and less problematic to use regions than trying to split out the files:
#region - TextBox Events -
private void txtNews_TextChanged() {...}
private void txtDir_TextChanged() {...}
#endregion
#region - ComboBox Events -
private void cmbNews_SelectedIndexChanged() {...}
private void cmbDir_SelectedIndexChanged() {...}
#endregion
which, when collapsed, looks like
- TextBox Events -
- ComboBox Events -
You could also consider a tool like Ora to navigate large files: http://ora.codeplex.com/ JetBrains' Resharper also has an excellent file-structure viewer.
You should probably put each GroupBox into a separate UserControl.
You could:
Split the codebehind into extra parts, beyond what the designer sets up for you so it can keep its code "safe".
Create a user control for each GroupBox, possibly even the same object set up with different names and contained controls.
Just rearrange the handlers for controls by GroupBox within the single codebehind, extracting lines from common methods (Bind/Unbind-type behavior) into groupbox-specific methods.
You can create partial classes, if you want more than one code file. It looks like:
public partial class MyClass {...}
You can, optionally, add a DependentUpon property in the .csproj (I don't know of a way to do this other than manually edit the .csproj). This joins them together in the IDE. It looks like:
<Compile Include="MyClass.Controls.cs">
<DependentUpon>MyClass.cs</DependentUpon>
</Compile>
I'm a little worried that you're talking about the auto-generated code in the .designer.cs file... you don't want to change anything that VS generated for you... if you do, you will lose all your changes the next time you change something on the form, because VS will regenerate it!

Categories