(nested) user controls within a mvp pattern causing sporadic problems - c#

I have a serious problem with nested user controls (UCs) in WinForms while trying to implement the mvp pattern (passive view). The project consists of one model (designed as a singleton) and a set of different presenters with corresponding view interfaces. To avoid one huge view interface and therefore an overloaded main UI, I decided to make use of a set of different UCs. Each UC has one view interface and one presenter that can access the model. But there are nested UCs: meaning that one specialised UC implements sort of a basic UC. The main UI just represents a container for all those UCs. So far, so good (if not, please ask)?!
There are two problems that I am facing now (but I guess both are of the same origin):
From time to time it is not possible anymore to load the UCs and test them within the Visual Studio 2008 User Control Test Container. The error message just says that a project with an output type of class library cannot be started directly etc. I can "handle" that by unloading all UC projects and reloading them afterwards. (I guess the references to all mvp components and other UCs are then updated).
Assuming that the implementation of my mvp pattern is okay and all those UCs are testable within the VS Test Container at a certain time - there is the biggest problem still left: I am not able to add any UC (even the basic and unnested ones) to a simple Form (UI).
Could it be that my basic UC causes all these Problems?! It consists of two simple ComboBoxes and implements a basic presenter and basic view interface. Whenever I add this UC to a different UC the VS designer adds two references to the public getter methods of the UC as resources. I then manually remove those resources from the resx-file and commend the corresponding lines in the designer file.

For the second one: You should use DesingMode property of the Component class (which UserControl derives) in your code. Be aware, there is a bug with this property not having correct value with nested user controls.
This can help you, I think: When your WinForms UserControl drives you nuts

Related

Keep Methods for Form in Form Class, or Put in Unique Class?

I have a form with 3 tab controls on it, and each tab control has a dozen or so text fields. Right now I have all of my methods for modifying the text fields within Form1.cs, which is working, but is a very long class. I am curious if it is propper method to keep methods that call Form controls within that forms class, or if you should divide them out into other classes? I read this thread and I may be confused, but it sounds like the chosen answer is saying you should not try to access form controls from other classes?
How to access form methods and controls from a class in C#?
The best method for encapsulation in this scenario is to create user controls that contain the text fields for each tab. Then, each tab just has a user control on it, and all the logic specific to those fields is encapsulated in its own control.
if you can leave the code that accesses UI data inside the Form, but the code that operates/executes computation over that data into another class. In this way you will be able to create a single class, or a set of classes, which can be used for (say) UnitTesting.
It's easily done, you just pass a reference to the form to the other class, but then they become tightly coupled and therefore fragile.
A better option would be to define an interface and have the form implement it, that can get messy though.
Other options would be move the controls on your tab to a user control or even just another form and then host them in your main form's tabs. Then you could isolate the data and operations of each tab. Again defining and implementing an interface or two will help you decouple.
Think of it this way, you separated out the UI in to tabs, there is some underlying logic behind that from a UI point of view so it follows, there should be some logic in terms of separating the functions the controls on the tabs perform. I have seen exceptions to that, but it was usually because the separation in the tabs had no logic at all.
There are different ways to organize applications. It is usually a thing to separate the GUI (the forms) from the other application logic. Do only display logic in the forms. Create data classes (also called models) for you data. You might want to have classes like Customer, Order, Address and so on. These classes contain the "business logic", e.g. the Order class knows how to calculate the taxes, not the order form.
You can save you a lot of effort by using data binding to bind your business objects to the forms. See my SO answer for the use of data binding.
You can go even further by separating the logic into three parts by using the MVC pattern. I am not going to explain it in detail here. Just this, MVC stands for Model View Controller. Model is the business class, View is the form and Controller is a class that manages the model and the form, loads and stores the model etc.

Adding new Classes to a wpf

How can I expand the implementation of a wpf using my own custom classes? In particular, I want to create new C# classes on a wpf beyond the ones that derive from App.xaml and MainWindow.xaml. Should I add them directly on the project? If so, can I use references of the MainWindow elements inside them in order to tweak their functinality and add new tasks? Should they derive from the MainWindow class?
What is generally the most reasonable way to expand the implementation of a wpf to other new classes?
That is a rather broad question and where to place classes and from what classes to inherit are quite different problems. Both are ultimately a question of architecture though and what the right architecture for your application is cannot be answered here. It depends on what your application is supposed to do and how it should be done, all that should be planned out before doing anything with classes. You might want to read some smart book on topics such as software engineering and software architecture.
Ultimately you should get a good book on WPF, read it, and type all the examples into your editor. Simply trying to dive into an API with absolutely no example and no concept of how the architecture works is not going to get you anywhere very fast.
To answer your specific questions, though:
Should they derive from the MainWindow class?
No. To write the GUI for a WPF application, you rarely will have to use inheritance that isn't already written for you when Visual Studio generates a new app, a new window, or new user control.
It might make sense to use inheritance in your code somewhere, but rarely in the GUI code itself, and certainly not on the window or app level. The only manual use of inheritance will be for implementing custom WPF controls (the least frequent and most painful option for extending your GUI).
How can I expand the implementation of a wpf using my own custom classes?
It isn't clear what you're trying to do, so I'll try to cover all the cases.
UI
If you want a new application, usually you wouldn't derive from a specific application class at all, you'd just create a new WPF project (a whole program). Visual Studio will then create new classes for you that inherit from Application and Window.
If you want a new window, the same thing is true. You'd just tell Visual Studio to create a new window, and your classes would automatically be created for you, and they would inherit from Window.
If you want to add existing controls to a window, don't derive from anything. Go to the UI designer, and drag+drop controls from the Toolbox onto the page. Or edit the XAML for that window directly.
If you want to customize what happens when a user clicks on or works with a control, write event handlers for those controls. Or when you're comfortable about this, read up on data binding and the MVVM design pattern, since it will help you write cleaner programs.
If you're trying to customize the way your app or controls look, you'd usually use data templates, styles, user controls, and custom controls, in that order of frequency and difficulty. Except for custom controls, none of those involve manually written inheritance. When you add a User Control in WPF, Visual Studio will write a class that inherits from something, but you don't have to worry about that fact.
Non-UI
If you're trying to write the guts of your application, you probably should avoid writing any UI code.
It is a good practice to separate your UI from your main application guts. That way if a brand new technology comes out, you can strip off the UI, and throw the guts into a new program. Or if you decide to put those guts into a web page, that will also be possible.
You can reference this new code from the code-behind in the UI, or using the MVVM design pattern (which you should eventually read up on), but you should avoid mixing your UI specific code and your non-UI code as much as you can.
This means you won't inherit from any UI classes in order to implement the guts of your app.

WPF Best Practices: Do custom controls work well with the MVVM design?

I was looking at creating a common control that I will be able to reuse on my pages: an AddressControl which has Address1, Address2, City, State, Zip, etc...
Originally I just created a class (AddressEntity) that contained all these items and implemented INotifyPropertyChanged. I included that class as a DependencyProperty in my Code-Behind for the AddressControl and used it as the DataContext for the bindings to its properties.
Then, someone said my code was ugly and I should look into MVVM. Looking at it, I assume that:
AddressEntity.cs will just be a container of data (i.e. Address1, Address2, etc.) and members (i.e. Clone, ToString, etc.)
I need some AddressViewModel to wrap my AddressEntity in and provide the PropertyNotification Changes, Validation, etc.
I need to somehow have a "View" for this.
The problem is every example I've ever seen has a UserControl as the View and not a CustomControl. Before I delve too deep into this...
Is it possible to use MVVM + Custom Controls for this example?
Is it pretty much the same thing (UserControl vs CustomControl) as the View with the exception of primary differences of UserControl vs CustomControl? Basically, is my CustomControl really just a View?
References: The Model-View-ViewModel (MVVM) Design Pattern for WPF
CustomControls are never done with mvvm.
What you want is a reusable view(user control) of your data and not a control(custom control).
UserControls and CustomControls are two completely different beasts.
EDIT:
Notwithstanding why UserControls were originally developed, in MVVM typically you use a UserControl when you want a reuseable view which is specific to your model/viewmodel. Its just XAMl without any code behind (except for the auto generated InitializeComponent stuff). Generally you keep a UserControl in the same project that you use it in.
You go for a CustomControl when you want a generic piece of functionality which requires a view and which has potential use even outside the scope of your current application. Here the control is actually defined in a code file and the look (which can be overriden) comes via XAML in a resource dictionary.
Generally you keep a CustomControl in a a seperate ControlLibrary project and reference the library in the project you wish to use it in.
With due respect to WallStreetProgrammer, choosing between a user control and a custom control based solely on whether or not you want a lookless control is a bit naive.
When using MVVM the Model and ViewModel should not be dependent on the View, that is they should not care what kind of view use them.
The difference between a custom control and a usercontrol in WPF is that the custom control is lookless and can be customized via its ControlTemplate. This is what you should write if you are writing a generic control library, like Microsoft does. If you however have a specific look in mind for you control, just go with a user control, it is much faster but will only have one look, the one you define for it.
It is common to use a mix of custom controls and user controls in a MVVM project. For example you would probably use a bunch of custom controls from Microsoft (like textboxes and textblocks) and combine them into user controls.
See Control Authoring Overview

MVP and multiple User Controls

I’m trying to use the MVP pattern and I’m running into a design problem. I’m developing an application that will have several UserControls. The UserControls themselves have nothing to do with one another and only represent a subset of the actual model. From what I’ve read, people tend to say you should use one Presenter per View. This seems to make sense, but if I have 30 UserControls, do I really want 30 Presenters? On the flip side, if I have 1 Presenter and 1 View that represent the entire “application” view, then I’ll have bloated View and Presenter interfaces. Then each View would have to implement methods that have nothing to do with it. My question is, is there a better way to handle multiple UserControls, or should I just create 1 Presenter for each View?
You should be doing one presenter per one control because of:
that would allow you to have focused unit tests tackling only that control
increased maintainability due to the fact you won’t need to support gigantic presenter containing union of presentation logic of all controls
that would prevent redundancy in cases of having same control on multiple pages
Increases SRP by having controls focusing on their specific logic while the page performs container specific roles:
There are two problems usually mentioned related to the decision “presenter per control”:
Shared context is problem where due to the fact that all of the controls are just showing different pieces of the same page data context, that situation may look like a problematic use case leading to a lot of data retrieval redundant code in every of the controls.
That is easily solvable through dependency injection where page (or controller) performs single data retrieval and then inject the data context object into every of the presenters\views (usually implementing some interface enabling that).
In case of MV-VM pattern (Silverlight, WPF) same effect can be achieved through data bounding where the page would set its DataContext which would then be used from views itself
Communication between views on the same page is second problem which is easily solvable using couple of approaches:
Controls are publishing events to which page subscribes and then makes direct calls to appropriate methods in other controls (page is container to all controls meaning it is aware of all of their members)
Observer design pattern
Event aggregator pattern
In each one of this approaches controls are communicating with each other without being aware of each other
It would make more sense to group the code that is related in one object. So, in this case, if the views are specific groupings of related code, then the presenter would also mimic these groupings. To have a "global" presenter for different views would group unrelated code in one object. It would definitely bloat the interface for the presenter as well. Check out the single responsibility principle.
Now, you could have one Presenter Manager class perhaps that could give you access to each presenter interface, like the Interface Segregation Principle states, by either inheritance (have a global concrete presenter that implements many presenter interfaces..which kind of violates the single responsibilty) or aggregation (having individual presenters for each interface and get functions...thus the global interface would the the get functions) or a combination of both (global presenter being somewhat of an adapter).
I think the best solution though would just to have 30 different presenters.
Each View doesn't have to implement the same interface... Why not define the interfaces for each control, and have one Presenter for the entire screen that contains all the controls? The Presenter can "wire up" the events on each view according to what interface defined events each view requires, to appropriate event handlers on the Presenter (and on a controller if you are doing MVPC). You may also need another interface to represent the Presenter functionality that ALL view need access to in common...
If you're doing MVPC then view events that affect the Model wopuld be "handled" in the Controller, whereas View events that only affect other parts of the View would be handled on the Presenter.
Old question, but I'm going to pipe up and have to disagree with the other answers:
you don't want one presenter per UserControl, any more than you want a unit test on every UserControl - that would be a blind misuse of a design pattern.
A UserControl is not a View.
Each logical area of your application should have one presenter; how each is broken up - how many controls, what shows what - is solely a concern of composition.

Using DesignMode property vs. LicenseManager.UsageMode

I've seen multiple posts and questions about the DesignMode property of Forms and UserControls. The idea is that you want to check if the control is in design mode (e.g. the control is shown in the Visual Studio Designer), and avoid code that can only be run in, well, run-time.
The problem I've seen many have - and my failing memory exposed me to it too, recently - is that the DesignMode property does not work in the constructor, and does not work for the nested controls.
However, it works extremely well in the Load event handler for your control or form!!
When you think about it, the code in the constructors of the Forms or UserControls should only deal with state that does not require the form to be loaded.
Code dealing with UI objects initialization should maybe be located in the Load event handler for the control. And in that function, the DesignMode property works. The Designer will use its proper value at that time.
In principle, the InitializeComponent() method has been called but in reality, when you show the control in Design view, the Designer only parses that function, it does not run it. The Designer, however, does run the constructor of nested controls.
If you absolutely need to put initialization code in the constructor, use theSystem.ComponentModel.LicenseManager class, it has a static property called UsageMode which takes values of DesignTime or RunTime. You can absolutely trust that property in the constructor of your control - but in the constructor only!
I had forgotten that little subtlety in the app I am working on at the moment. To get around the issue, I am adhering now to the pattern that all controls and forms which need extra initialization must implement a handler for the Load event. There, the DesignMode property works just fine, and I never have trouble opening my user control and forms in the Designer.
If I have a class hierarchy, I sometimes make that event handler virtual protected, and I only override it when the subclass needs extra initialization.
I am wondering, though, if there are better methods out there, or if there is something smelly about this pattern (other that having to implement a Load event handler many times?)
Because of the issues with using the DesignMode property with nested controls (and related problems), my general approach to this problem is to not even try to get my custom UserControls to function in design mode. Usually my controls are very complicated and owner-drawn, so even if the DesignMode worked with nested controls, it would take a great deal of programming effort to get them to show anything meaningful in design mode (and it would slow down development work, because the controls require a significant amount of initialization and setup time).
Usually I just add a public Setup() or LoadData() method that does all the work, and only call this method at runtime. In design mode, then, the UserControl just shows up as a square, which helps me position it and nothing more.
I'm interested in seeing if you get any other answers to this question, however, that might address your problems.

Categories