So I've just started developing C# WinForm applications and each project I've been working on seems to be larger and requires more user functionality. If I add all of the functionality to one form, obviously it can get out of control very quickly. My last project I would divide up the functionality into individual Forms, and whenever someone say wanted to perform "Feature1" I would instantiate Feature1 Form and show it as a dialog with the main Form as it's owner (so they couldn't click off it).
I'm just curious of what other methods are out there for keeping code organized within Forms. If you are forced to have tons of features/functionality on a single form is there a good way to keep items organized? I simply hate having a code file with hundreds/thousands of lines long.
The answer may simply be in the design, try to design the UI up front so you can utilize multiple forms?
Another example I faced. I created a Tab Control and had about 5 tabs. Those 5 tabs had tons of features and were all stored in the same CS file. What other options did I have? Create a new custom TabControl class with my specific functionality for that tab in it?
I don't mind reading, so if there are decent articles out there feel free to link them!
The go-to method is a Controller/Presenter. The idea is that the window should only be responsible for actually handling the UI events of its controls, and it should do so by calling methods on a Controller which do the real work for the window. The window can either have the handlers necessary or it may link the UI events directly to Controller methods; the former is usually the easier method, but it can be tempting to sneak in a line of code here or there that really should be in the Controller method. By doing this, you sever the layout and presentation logic in the Form class with the business logic in the Controller.
Mark Hall's suggestion of User Controls is also a good one. By creating UserControl classes for tabs or for common UI control combinations, you sever the logic responsible for laying out that part of the UI from the main form's code, and the control then just "drops in" and the window works with it in a much simpler way. This is a must for implementing custom but reusable controls; the fundamental tenet of DRY is that if you have two lines of code in two different places doing the same job to two different but interchangeable things, those lines of code should be merged into one place.
I have used UserControls in my projects to group functionality into separate objects that can then be added to your Form.
I tend to split my logic code from the UI as recommended. If you do this, you need to be somewhat cautious with how calls are made across the application to avoid Cross Thread Exceptions. I was taught to create delegates and events to update the UI from the logic class, but MSDN of course also has a lot of information on making thread safe calls.
I know this is a late answer, but if anyone still reads this question, another way to reduce the number of lines of code in your form is to use Data Bindings. If you are using properties, Data Bindings make it so that you don't have to constantly write handlers just to do something like PropertyName = textBox.Text;. Data Bindings work with both datasets and objects.
Related
I want to ask pro developers out there that how they manage a big windows form class. Is it a good idea to split it with partial keyword across different files? That's the thing that I was doing so far, but it creats unnecessry designer files that when you double click on them in VS, a blank winform will pop up:
So what I do, basically is group events and code logic for each related group of controls in one file.
My answer is "I don't". If you need a lot of code in one single class (in this case a form) it usually means your class is doing a lot of stuff and you need to make it less coupled. A good way to achieve this is to use a sort of MVC or MVP pattern form putting the logic in another place, and to use UserControls so you could have the different functionalities in different controls (with their controller or presenter, depending if you implement MVC or MVP). Divide and conquer.
I not consider me an expert, but once we had a similar problem with a main form that did not stop growing up.
The solution was just OOP, make unattached and reusable classes, those can be in the same namespace with internal visibility.
For Example there you have a ComparisionForm.Menu that looks that can be unattached from your main code in ComparisionForm.
From another point of view 'Readability'.- Partial classes are useful but take into account that even with that division of code in different files, the logic is not always divided, that makes the code hard to read, understand and finally hard to maintain.
Divide logically my classes for my was the solution. You know what say they "Divide and Conquer"
I think the best way to separate the code of a form, it's to use UserControl.
And in my case, when I have a big class, I use region instead of partial class.
Not a pro, but my two cents are: Don't have a large class. Extract most of the code to other classes.
You'll gain, also, that you'll be able to make most of the methods private, thus reducing Intellisense "noise".
I'm writing a flashcard program and am running into an issue I always seem to face when writing this sort of Forms program.
I'll describe the program then the issue.
In this program, one main form controls almost all of the action. Depending on the user's input and form events, different buttons/controls may become enabled or disabled, text in various boxes may be populated, etc.
For example:
Some questions might be multiple choice and others require typed input.
The user inputs their answer and clicks a button -- if they get something wrong, they have the option to override the 'wrong answer' judgement and say it was really a different, correct variant.
Statistics regarding which questions were answered correctly are kept and used in the decision about what flash cards to show next.
Now the issue.
How do I best create a clean interaction between the "form" code (for example, handling the OK button's onclick command, and enabling or disabling various controls) and the "logic" code (underlying data stores, program logic that does not have immediate implications for display)? If it is all mixed together in the form object code it does not seem right.
Can anyone suggest a design pattern (especially one widely used) that manages this cleanly?
In case it is relevant I am thinking of something like this:
Object Model:
Class MyForm: the form itself.
Class FormController:
Child class of MyForm.
Instantiation requires an object of type MyForm.
FormController's job is to put its MyForm object into a particular "state," by enabling/disabling controls, displaying various text, etc.
FormController exposes a small set of public functions which deal with semantically high-level request for the form state (such as "DisplayNewQuestion(QuestionData d)")
Class Session: Contains all underlying persistent data or objects involving this session, including lists of possible questions, objects that select the next question from the list, etc.
Class Driver: Drives both the Session and FormController objects. For example, it would ask the Session object for a new question, and pass it to the FormController object to update the form.
The advantage to something like this is that icky form code and nice logic code are now completely separable. But is it worthwhile? Are there better or more common design patterns for this?
Thanks a ton!
I am always most comfortable with Model View Controller in this situation. The Shade Tree Developer wrote the most informed series I have ever read on the subject, see here
The jist of MVC is
Model contains the data to be displayed
View is your form and only has logic for displaying and informing of user interactions
Controller contains the glue to make it all happen, including the business logic.
The depenencies should be
Model doesnt know about the view or the controller
View knows about the model and knows how to extract data from it to display
Controller knows about the Model and the view, instansiates them both and wires them together.
The model raises an event when it changes, the view captures this event and refreshes its display accordingly.
The view raises an event when a user interaction occurs, the controller captures this event and performs the correct action for the interaction whether that be updating the model or saving or clearing or whatever.
The view should not write to the model itself
You will see a lot of code where the form creates the controller but imo this is wrong. It came about because of people trying to apply this pattern in asp.net webforms where you have no control over the lifecycle, the first thing that always got created was a view so you had no choice but to have this create your controller, however in winforms you are in control, so make it clean, have the controller create the view.
You might want to use the Model-View-Controller (MVC) design pattern, in which the "logic" is your controller and the "view" is your UI. The model is used to access and retrieve data from your data source (a SQL database for instance)
It is worthwhile to separate your logic from your UI, because it makes them more maintainable. For example, if you want to change your UI from a winform to a web page, you don't have to redo all your logic.
Also, it makes up for a really cleaner code. Using design patterns in general helps other programmers understand your code faster as well.
What is the best way to write the code ?
(1) Like directly writing the code in the button_click() event.
or
(2) Make the function of that code which I write in button_click() event and write this function in one class and then that function I should call in the button_Click() event.Like is it called three-tier approach to write the code ?
Like in button_Click() event I write the code to save the records in csv file from datatable.So I should write that code in button_Click() event or I should make one new function and one new class and write that code in that function which is the new class and calling that function in button_Click() event.
This is only one example but I am talking about all the code written in my application that which is the appropriate and best way to write the code and what are the benefits ? Note that I write the code in Winforms with c#.
You should go for the separate function in a different class. You should do that because you'll make the code reusable and create a decent separation between the user interface and application logic. Like this, you could for example change the UI without affecting the rest of the application.
Also take a look at MVC pattern, you'll understand better the whole idea.
The only situation where i think that the first option should be used is when it does some action that will affect the UI, and still i'll create this in a separate function inside the Form class.
If it's affecting the UI, it should be in the same class because it's related and for example if it's a code to refresh a grid i'll put this in a separate method inside the same Form class because this could be used in different places inside it. So changing the UI has no impact on the application, you just make your code reusable & maintainable.
It all depends on situation.
If you are going to make updates to the Form, then it's better to have the updating code in the Form. However, if there are lots of processing, then surely it's better design to have a separate class handle the job.
It all depends on situation.
Generally, you don't want any logic in the event handler, since GUIs tend to provide redundant mechanisms (context menu, menu bar, toolbar, accelerator key) for triggering the same command, and the event signatures aren't compatible for all of these. Then the question becomes whether your common function should go in the Form class or into the data model.
I often start out with the logic in the Form and then refactor it into model classes as needed. Many small apps will never get large enough that multiple classes are required for maintainability. As long as you avoid code duplication (i.e. copy+paste) then refactoring will be straightforward later if you find you need it.
It is always good to develop classes for jobs. As it makes your code reusable and it also implement three tier Architecture. The benefit is that it is easy to understand.
The important thing is that, it is only beneficial if you develop your classes appropriately. Develop methods in the class which can be reusable for you.
The another benefit is that it hides the complexity of your code.
There are two general approaches to adding structure to code: top down and bottom up. Top down structure comes from design work that can involve a formal or informal process and pure design artifacts like UML diagrams or functional specs. The ultimate goal in a top down process is to create classes and interfaces in your code that will provide appropriate structure to make your code maintainable. This can happen before you write the code, or as part of an iteration, but the idea is that you create the structure first, then create the code.
Bottom up structure comes from refactoring. For example, start with all your logic in a button click. When you add a menu item that does the same thing as the button click, move the code for your button click function into a private member function on the form. When you need the same features in a different part of the application, encapsulate the code and state variables used by your private member function into a class.
I'd recommend using both approaches. The right mix for your situation depends on the development team (size, location, ability to communicate) and the size of your application. Generally speaking, large applications require more top down, and on very small applications a minimal amount of top down design is adequate. But there should always be some high level planning, even for a small app.
We've been using the MVP pattern and Winforms with a fair amount of success. However, a question always pops-up about MVP:
What is a good granularity for presenters?
What I mean by that is: With Winforms, a fine-granularity usually works quite well for user controls. That way, it's easy to reuse user controls and use them as building blocks while designing more complex GUIs. However, having the same (fine-)granularity with presenters seems to be a problem.
On one hand, having coarse-grained presenters hinders the ability to use "plug-in" controls and it sorts of violate the DRY principle: Multiple presenters often need to implement the same logic (populate a list of customers, for instance), which is used by multiple, more complex, controls.
On the other hand, fine-grained presenters seem to limit the ability to reuse controls in different situations. For instance, an editing view might sometimes need to save the customer right away; sometimes it needs to link it to something else; sometimes is just needs to validate it; and so on. It often depends on the more complex control. But there's also a fair amount of shared behaviour.
Note that, in both cases, 1-presenter-1-view is achievable. What is considered "1-view" changes.
What is usually considered best-practices for presenter granularity using MVP and Winforms?
Fine-grained presenters and customizable behaviour through options or something of that nature?
Coarse-grained presenters and low presenter reusability?
Something else?
Disclaimer: We mainly use Supervising Controller but I think it also applies to Passive View. Sorry for the long question, too.
We use MVP at all of our clients and this is definitely a conversation that comes up in more than one occasion. How clean should our code behind classes and presenters be? Having said that, we have chosen to use the coarse-grained presenter approach. Basically, every form would have its own presenter and would only get and set properties of any of the controls on a particular form using its view. Populating controls-a call to a db to populate a combobox for example-is located in a public service class. Any validation of user inputted data is located in a BO class which can be reused by any and/or all of the presenters. I hope this helps.
In my CAD-CAM system my presenters don't use user controls. User controls reside in the view which reside in a EXE assembly that implement the view interfaces the presenter use.
If want to display a list of customers I hand it off to the view which has a DisplayCustomerList and it uses whatever combination of user controls it needs to display the customer list. If multiple views show the customer list in the same way then in the ExE/View assembly they share a user control or class for doing that. That class doesn't go outside of that assembly.
Our software is adapted to run many different types of metal cutting machine. So we place a lot of emphasis on being able to rip off the UI and replace it with a completely different UI (corresponding to a different machine). All of these UIs reference the same set of core assemblies.
The hierarchy looks like this
View EXE
Presenter Implementation
Command Assembly - commands are executed by the presenter that modify the model
Presenter Interfaces
Model Assemblies
Off to the side are loadable assemblies that define dynamic content like what file types can be loaded, reports, cutting device drivers, etc. These implement various interfaces found in the model assemblies
One thing I do is that I don't impelment a view presenter for every dialog. If the dialog is tightly bound with a command then it is defined, created, and used along side the command class. Occasionally a group of related commands will share a dialog (File handling for example).
The essential question I ask when using MVP is "What happens if want to completely replace the forms with something else?". The answers to that question will identify where you are too dependent on a particular user control or form engine.
The biggest problem (and one that I haven't got a good answer for) of my setup is that current IDEs and langauges make it very easy to tie user controls to database records. It is so productive compared any other setup it tends to dominate the design. I haven't had to deal with the issue much in my CAD-CAM application so I don't have any answer other than passing the dataset to the view and let it handle it. This site has some patterns that may be of use in this situation.
I have two forms, form A and form B. These forms must differ in appearance, but they share a lot of logic. The problem is that this logic is tied to the appearance (validation on button click, events being fired, etc.). For example, I have a name field, and when the save button is pressed, I need to fire an event which causes the parent form to validate the record name to avoid duplicates. Both forms need this logic, but their save buttons are in different places, and the tooltip that is shown when an error occurs also needs to appear in a different place. This is just one example, but does anyone know of a way that I can avoid copying and pasting code here? Perhaps I am missing something obvious...
You could create an object with data that is represented in both forms, and put validation logic in that object. The presentation layer should populate that object with the entered data, ask the object to validate itself, and then handle validation errors in a form-specific way.
If the common logic is UI related you need to create your own custom form class (that inherit from Form class) with the desired logic. then all you need to do is inherit that class in your forms.
If the common logic is less UI related create an internal class that encapsulates the common logic and call it from both forms.
You need to add a Controller between your 2 views and your shared model. This way you will just need to do : myController.save(); instead having to call you model object to save them in both winform.
There are few ways that I can think of to refactor these forms to share logic. You could use one or more of these in conjunction:
Create UI specific "bean" objects that wrap your business object and adds additional functionality that is shared between forms. This bean can do things like create tool tips, assist with validation, eventing, etc.
Create a helper class with common functions. Generalize the logic on the two forms to call this helper class for common functions.
Enhance your business objects to do your validation. I don't mean to say your BOs should be aware of any UI, but they could/should enforce the business rules. This might pull some of the validation logic off your forms and into a common location.
Create custom controls that are specific to the type of data with which you are working, and use those controls on the two forms.
You may also want to take a look at the CSLA Framework, I've used it pretty successfully in past projects to help reduce the amount of duplicate code between different UIs. It takes advantage of .NET's databinding capabilities, but I don't think it's required to use databinding just to get the most out of the framework.