Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I've got an WinForms application that uses MVP and I'm not entirely sure how to approach the scenario of when I need to create new UI elements.
For the sake of example, let's say my view has a button which is supposed to open a new view (Form) as a dialog. Is the view or the presenter supposed to create the new view or is it the job of the presenter?
This is my thought process:
The view should create it as it as a UI specific operation. But...
The presenter should do it because the view is just supposed to be passive. But the presenter shouldn't know the specifics of the UI.
Which is the correct way to approach this?
I've seen this done a couple different ways. It's funny how all the patterns seem perfect on paper and then implementation details show how it's not that simple. I'm going to give examples as a MVW (model-view-whatever) because it should be similar in any pattern.
Option 1:
Bind to a property. This is a little more difficult with WinForms but works great with WPF. Have your button set a bool property on your presenter/controller/viewmodel. Your view then simply shows or hides it's UI based on this value. The UI can overlay all existing UI to have the appearance of a modal.
Option 2:
Services. Introduce a DialogService (hopefully you have dependency injection set up so it's trivial to add). This service has a method of ShowDialog(options). Options could be title, message, commands (with titles and actions for button). Have your button set a property or fire a command on your presenter that then calls it's dialogService's ShowDialog method. This way your view is still just simply calling your presenter and it is using the service. Views shouldn't know about services. This allows your DialogSevice to construct the appropriate UI and then launch the new form. This is also how I like to wrap up the native MessageBox.Show calls so you can replace all these with a DialogService.
Option 3:
Don't be a purist. If your modal doesn't need to interact with a presenter or you simply want basic data back (say a color picker or something like that) then just let your view take care of it. Your button can simply open the modal, the modal has values that are sent back to the view. Then your view uses them. If the data has no reason to make it back to a presenter, don't over complicate things to be a purist. Views can still perform UI based logic. I use the view for many UI only things such as moving elements around with mouse/touch events or pinch to zoom calculations. If logic is UI only, keep it in the view's code behind. If it's repeated UI logic move it to a service or user control or custom view.
In all the MVP/MVC/MVVM docs, they are always missing crucial details. To me, Services is the missing link. They allow loosely coupled logic to be plugged in and you can wrap up some of the ugly UI bindings or UI events into services and keep things tidy.
Hope this helps.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I have a C# project that needs to refactor. Project uses WPF+MVVM Light toolkit. I found the MainViewModel(...) constructor that receives about 50 parameters (factories interfaces). I think not. Am I right? I'm interested, because I want to improve my OOP thinking. Thanks.
P.S. Sorry for my grammar. Check me if you find errors.
Clean Code: A Handbook of Agile Software Craftsmanship, page 40, states that...
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification - and then shouldn't be used anyway.
Consider the book as guidelines for software design, and as such, recommendations when thinking about your code structure.
50 factory interfaces means your ViewModel is way too big and trying to do too many things at the same time. You should break it into separate ViewModels that will appear as properties on the main view model.
WPF allows composition and any framework that allows ViewModel first (ie anything except PRISM) will compose the corresponding views form the ViewModel it encounters. I'm not sure about MVVM Light but with Caliburn.Micro this is almost a non-issue.
If MVVM Light doesn't automate this, you'll have to bind the WPF controls that will contain a specific child model's view to the child model property on the main view model.
Another option is to bundle multiple factory interfaces into parameter objects and pass these to the constructor, bringing the number of parameters to 4-5 instead of 50. This is the Introduce Parameter Object refactoring. Some tools like ReSharper provide automation support for this refactoring.
If you combine this with a DI container the parameter objects can get initialized automagically simply by registering the individual interfaces.
The best solution though is to break the main model into submodels
You might look into using a Dependency Injector like Unity. Register all your Service, Factory, and associated Classes you need with the Unity Container and then you only need a single parameter for your ViewModel constructor which is the Unity Container.
50 parameters for a constructor seems insane to me...
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
In theory a large 1000+ line of code behind code is "bad practice" what if the majority of the code effects controls on the page?
For example what if there were 30 text boxes to collect user data, but depending upon answers to questions, visibility, validation, etc changed on these text boxes.
Should you then be writting methods in classes for validation that take collections of text boxes and disable validation, or set the visibility? I'm having a hard time wrapping my mind around the design practices of large code files.
I guess I'd like to know the best practice for breaking out large code behind files that still allows for easy control manipulation.
I'd devide the text boxes into groups depending on the contents. Make a User Control for each group (With a dedicated visual container). A user control can take care of validation and some computations, but it is very readable and can event be reused somewhere else if the problem you are solving allows that.
Another option is to use a wizard. This could be more complicated, but if you have the time, you can get nice results.
First of all I do not think 1000+ is not too much for a code behind file at all and I wouldn't consider this bad practice as long as you follow the DRY ( do not repeat yourself ) approach. If you really want to split this up there might be a possibility to have more code behind files for group of controls and do ajax requests to validate parts of the page. You could then evaluate the results from the ajax calls and check if the return message is success and assume that the validation is successfully if all individual ajax calls have a success flag.
For ASP.NET I do most of the logic on the client side with the knockout framework using the visible binding:
http://knockoutjs.com/documentation/visible-binding.html
I use knockout to generate the controls via foreach binding and set the visible binding to an observable inside the obserable array. If the array you pass to the foreach binding is an obserable array you can also add / remove controls via JS.
You could use a validation framework and on validation you can change the observable array adding more questions / removing questions from HTTP post.
Another option would be to do the validation on the server side.
You can check in the post method the values which have been submitted and change the view model adding or removing elements. You then return the view with the modified model.
If required I would use a strongly typed collection to have a reference for the page elements and modify the properties as required.
For WPF I use Observable collections to track property change events which notifies the UI when the collection changes.
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.
I have a split container in the left panel is a user control with buttons. In the right panel is an initial user control that will change based on which button is pressed. What I want to know is how does one let the Form with the spilt panel know to paint in view x from the presenter of the button view?
In theory, the Presenter should have access to the Views, in which case the Presenter should be notified about any button clicks from the view in the left panel and then update the Form to show the view in the right panel.
How exactly this is accomplished depends heavily on your specific implementation. Architecture patterns are guidelines... there are no hard and fast rules which one must follow (unless you are using an MVP library of some sort, in which case you will be constrained by that library's implementation).
EDIT: To answer your question below, Chip...
Again, that is wholly dependent on your implementation. In some cases, it may make sense to have one massive Presenter and dozens of views. In other cases, it may make sense to have one presenter for each view. Even if you have multiple presenters, though, you will still need to maintain a hierarchy so that the presenters can talk to one another. So somewhere, at some level, a presenter is going to have knowledge of both the button click and the empty container waiting to be filled, even if that knowledge comes indirectly through another presenter.
EDIT 2: (In response to your updated comment) There are no hard and fast rules, but one common trait among MVP implementations is that the Presenter retains at least partial control. That means that the Presenter must have some level of access to all relevant UI elements. If you nest views within views, then you'll still need to devise a way for the Presenter to interact with them.
A little while ago, I wrote this SO post looking for a good way to handle UI and business layer interaction, and I liked the answer which was to use the MVVM pattern.
So I did so quite successfully, but I'm a bit stuck with a problem using this pattern. Indeed, in some part of my UI, one of my buttons is supposed to open a dialog with the details of an item displayed in a ListView.
I saw this SO post asking about the same question, but I didn't quite understand the answer and I wonder if it is suitable in my case. The idea was to use the Unity framework and to call the window associated with the view in the repository using App.Container.Resolve<MyChildView>().ShowDialog(), for example.
However, my problem is that I have implemented the ViewModels in project separate from the UI client project. I did this in order to be able to use the VMs from another client if need at a later stage of the project. First question, was that a wrong implementation of the pattern?
Second question, as my ViewModels project isn't actually in the client's project, and hence I do not have access to the App global variable. Therefore, I don't think I can use the solution I found in the previously mentioned post. Is there any workaround?
1) Your implementation is not wrong at all. I regularly separate UI, VM, and models into separate assemblies.
2) As you mentioned, it isn't appropriate to reference App within a VM. Consider App a "UI class" and treat it as such. Have you considered injecting the appropriate UnityContainer into your VM?
If injecting the container isn't an option for you, think about adding a controller to your solution or using the Mediator pattern as suggested by other answers in that SO post you mentioned.
Try this. Set up a new thread, initialize and show your window (You can also use ShowDialog() instead of Show()), and then convert the thread to a UI thread by calling Dispatcher.Run() which will block until the window is closed. Then, afterwards, you can handle the dialog result however you want.
new Thread(() =>
{
MyDialogWindow m = new MyDialogWindow();
m.ShowDialog();
Dispatcher.Run();
// Handle dialog result here.
}).Start();
Be sure to add an event in your dialog for when you close the window, to have the Dispatcher stop. Add this to your constructor of the dialog:
Closed += (_,__) => Dispatcher.InvokeShutdown();