I could use some advice/help on a piece of software I've developed.
The application is a wizard style app where users fill out fields on each form before choosing to go to the next form or back to the previous. Fairly simple.
Right now the menu calls frmWiz1(InitialData) and when frmWiz1 returns with DialogResult.OK the menu will call frmWiz2(frmWiz1.Data) (not exactly, it stores all of the Data from each form, and passes those references in to the next form). Each data object inherts from an IPrintable interface that defines methods for printing itself, so at the last page in the wizard (print preview/sign), it adds each Data object to a custom PrintDocument object that just iterates through the data objects, calling their print functions and manages pagination etc.
Initially I thought this was a good idea but now I'm thinking that:
- The menu form is handling too much flow logic.
- The Data objects (which handle all of the business logic that applies to their particular set of data) should be decoupled from print logic (cause as they are now, they're in the printing namespace - maybe just a relocation will set my mind at ease).
I don't know. I'm decent with the language, but I'm still a rookie at design.
Screw "frm" prefixes!
With respect to the overall flow of the application, I would recommend using Application Controller or something of the kind in order to centralize the logic.
As far as the UI goes, each Wizard stage should be a separate User Control (with no "Cancel", "Finish", "Next" or whatever buttons) wich is placed on the root form with the aforementioned buttons.
No object should be responsible for printing itself - use IPrinterService for doing that.
Just a few general thoughs:
This is a great Wizard control. We use it here at work, and I must say this guy did a real good job with it. Not sure if it can be useful to you, but check it out
Figure out exactly what you need to know about an object in order to print it. Try to come up with methods and/or events that you would need an object to have in order to be "printable". Put those into an interface, and have your business objects implement that interface. Then, have your printing helper class deal strictly with interfaces.
Related
I have a (problem?) where my application's main form code is becoming quite large. Because it is the main section of the app, there are a ton of event handlers.
I really don't want to use partial classes to separate sections of the code because I might as well just use regions then. Also partial form classes don't show up in the designer and are in general just confusing.
Not really sure what to do to be honest. The file is around 1,000 lines of code while all my other classes are 10-150 lines each. I can't really encapsulate the behavior in to other objects because most of the event handlers manipulate controls on the form or member variables of the class and doing so would require a lot of parameter passing and confusion.
Trying to think of a possible course of action. I really would like to encapsulate a lot of the behavior in to other classes but the problem is the event handlers modify private controls and member variables. These classes would need to somehow have access to this data but I'd rather not just give an instance of the form to the class and make all the controls and member data public >.>
Any ideas?
Break it down into user controls.
Make sure there's nothing in the form that is not about presentation (display to the user, collection of user input). Move all data access out into separate classes, and the same for business logic.
Typically, this is done via encapsulating portions of the Form into UserControls, which manage their own internal events/controls. The UserControl can be passed/instantiated with the appropriate data from the Main form.
i originally had a main form with 2 panels, one had a graph in that i clicked on the other had the results displayed related to what you clicked.
All this code was dumped in the main form.
I tried to be a smart alec and use inheritance, so now i have a main form which has a graph objet and i have a superclass graph -> subclass specific graph heirarchy
however now when the graph is displayed in the main form, how do i get the data back to display in the other panel? The reason i ask this is now that the graph stuff is in its own heirarchy, it has no knowledge of the panel on the main form so i have no hwere to set the data when it is set
i hope someone can help
thanks
edit: i think i might just pass the control collection for the panel in to my graph class so i can add the relevant items in there
Depending on the relation between the two forms, you can use events to message data between them.
A click event handeled in the graph can raise an event with the data you need to display, which would end up on the owning form. Depending on the relationship, you either call a function on the 2nd form to display the data, or raise an event to which the 2nd form subscribed to send over the data.
[Edit]
I read Forms instead of Panels.
The main idea remains the same though. From your style of writing, it looks like you have an Objective C history. I know on the Mac, these things would be done in Interface Builder, setting bindings to make this stuff happen, but in the .NET Winforms you do these things in code (handeling events, calling methods, etc). If you like to stick more to the way it's done with Interface Builder, you might want to take a look at WPF applications; bindings work in a very similar way to how it's done on the Mac.
I would design this as an object that aggregates another object. Have a look at the way master-detail view works.
A winform forms.cs contains a gridview. This gridview(many columns) get populated with an xml elements and its attributes.
Another class "XMLReader.cs" that reads XML file and returns
List <someclassObjects>
Now I am sending gridview as a parameter from form.cs to another class "UpdateAppUI.cs" that receives the Gridview as parameter and update it.
Question is: Is there any issues with passing controls as parameter? Experienced professionals said donnnn't pass controls.
Then How I can access form controls to other classes?
What is the solution for above situation?
why you want to pass the grid view?
If simply you want to update it in UpdateAppUI.cs file then pass the datafrom gridview in the datatable. And from datatable you can update the database from the class.
No need to pass the control.
If you really want to pass the datagrid then create new object of datagrid as same as yours and pass that as an parameter.
I think that what those developers are refering to is: avoid making your UI unrepsonsive. You might want to look at your design ( read: conceptual model / design diagram ) before your deside how to implement this functionality.
There's an article on MSDN covering "Give .NET Apps a Fast and Responsive UI with Multiple Threads".
Consider this, if you have a Parent form that needs to update its child controls you might want to make the whole form accessable by the "update helper". But then again, try not to make to much heavy lifting on the UI Thread.
Also remember that your controls are Objects and when Objects are passed as parameters they are sent as reference types so another "danger" is that your method might do something malicious to your control.
To make the design understandable and manageable by others as well, I would step back one step and think about the design of your software.
I want to refactor some code.
Basically the code I want to refactor is a Form (using System.Windows.Forms;)
The way it is setup now, depending on which radio button you selected it shows a different layout for the window: different labels, buttons, etc. Not always a big difference, but different. This is a lot of conditional statement junk all over the place. I wanted instead to refactor it with the State pattern. There are three main states.
I'm not sure the best way to do this. Right now the IState interface has a DoAction() method which does some action particular to the unique State, and a DrawForm() method which re-draws the form based on the current State... However, to do the DrawForm(), the State classes need to be able to access the Form's member variables. That's what threw me for a loop. I didn't really want to expose them.
Is there a better way to do this?
You could make your state classes nested in your form. They will then be able to acces fields of form without having to expose them.
If your primary concern is keeping form stuff encapsulated, and you want to keep the state machine outside, I had a similar question a while back, you could check out the answer here - basically it entails creating a private inner 'action' class which DOES have access to form methods, then passing this to the state machine so that it can use the action class to invoke form methods indirectly.
I don't know if this helps, but why not have something like a strategy pattern for drawing the form?
So something along the lines of
interface IDrawStrategy
{
void Draw(FormType form);
}
And then when you pick which state the form is in, you can assign the form's draw strategy. Yes, you will still need to give the draw method access to the Forms variables to allow it to position them, but it at least allows you to make it easier to add different looks based on the states.
In wanting to extract the "state" of the Form, you are describing a pattern better known as a "Presentation Model". You will find some good information and tips on how you generally want the Form and State to interact by reading this article by Martin Fowler. In your case, your Form is the "View" and your State is the Presentation Model. As always, Fowler does a great job answering this question and more.
When looking into MVC frameworks for flex, as3, silverlight, and wpf... a common concept of ICommand / commanding keeps appearing... Can anyone explain the advantage of using ICommand / Execute() ?
Where I dont see the value added is - Why can't the controller map the input (ie: a click event) to the correct method inside of the model? I'm assuming it is because commanding buys you something - like removing business logic from the controller / the would-be event handler in the controller.
Thx.
Here's a couple of cases that demonstrate the value commands add:
Suppose you have a simple form with a text box and Submit button. You want a button to become enabled only if some text is entered into the text box. With commands all you have to do is to implement CanExecute method (to return true or false depending on the value in a text field) A framework will automagically disable/enable button accordingly. With code-behind (or controller) approach you'd have to write a code do enable/disable button manually.
Suppose later you decided you don't like the button control you used, and decide to switch to a new control (being that a button, or something more exotic) from a different library. All you have to do is make a change in XAML. Any control that supports Command binding will know what to do. In code-behind approach you'd have also modify your button click handler (since new control will probably require different event handler signature)
Suppose later you decide to add a checkbox to your text field that would visually indicate to user whether the content of that field is acceptable. All you have to do is to bind this new checkbox to your command's CanExecute, and now you have two controls already that would automatically change their visual appearance depending on whether form is submittable. With code-behind approach (or controller) addition of a new control would require adding more code.
Suppose you want to test your action. Since commands don't depend on any visual elements, and don't need them, you can easily write a unit test that will not require user clicking any buttons, or entering any text. With controller approach you'd have emulate controller's events, and mock the view.
Summarizing:
Commands provide a well-defined interface between the business logic and the presentation. Business logic implementor doesn't care about how visually certain action (e.g. command) will be implemented. He simply provides the action implementation and an ability for a presentation to query the state of the action. He doesn't care what particular UI element (or elements) will trigger that action, how exactly (in)ability to execute that action would reflect in UI, and what changes UI might go through in the future. At the same time presentation designer doesn't need to know anything about event handlers, controllers, etc. He has a Command and he plugs it in to any UI element (or elements) he chooses without the need to go to C# code at all.
What controller are you talking about?
The Commanding concept in Silverlight and WPF is used to tie together (through binding mostly) the UI to business logic (be it a controller/viewmodel/model/etc).
That is the point, to move the functionality of the command outside of the UI.
Example. Saving a widget in your application is probably always done the same way. Sure, you might let the user change the name, or this or that, but the overall behavior is always going to be the same. Now, in your application you might actually initiate saving a widget through a lot of different UI avenues such as Page 1 has a button on the right hand side that saves the widget on that page, Page 2 has a menu item on the top that saves the widget on that page. The UI is different but the behavior remains the same.
You can accomplish the same goal by using Event Handling (such as grabbing the click event on a button), but now you're back into the context of dealing with UI specific issues. Commanding, arguably, has a cleaner separation.
The simple answer is that commands are bindable whereas events are not. So if you want to respond to a button click event you can either:
Attach an event handler in the code behind.
Create a click command and bind it to the ViewModel's command.
Since one of the goals of MVVM (which is the more common pattern for Silverlight and WPF over MVC) is to seperate code and UI. So if you take the first approach you end up with code in the View. If you take the second approach you can seperate the code from your view using commands and bindings.