We’ve got some serious movements in the product development. And it goes straight in the right direction. There are three product teams, all of them want to use at least a variant of MVC. What is right approach? MVC? MVP? Passive View? Supervising controller/ presenter? MVVM?
There are a couple of questions to be answered before being able to decide. First of all, in which environment do we need this approach? The question has to be answered completely different when developing WPF, web pages as it is when developing WinForms.
Yes, good old WinForms, still state of the art. Let’s focus on that.
The first product just chosen a library that is available as open source called MVC Sharp. Not considering the old fashioned web site the lib is quite robust and stable. It follows a special kind of pattern, it uses “Tasks” to define the relationship between tasks and views. Let’s say, it was good enough. We use this term not to define that we aren’t in a mood to go deeper and make it better – we use it for saying that we don’t need to take another step as this solution is robust, maintainable and extensible. Plus it is understandable for the next developer. So any additional action may increase complexity or is additional effort in terms of time that is may be not justifyable.
That product has a “Configuration Tool” that allows for defining some system- wide settings. It is quite simple, just “default” controls like buttons, text boxes, radion button and check boxes, some combo boxes. Nothing special.
Good enough.
The other two products shall also make use of MVC approach. The user interfaces are much more complex. On one hand there is usage of Grids and treegrid controls, on the other there is the need to dynamically build up user interfaces. Let’s call the latter lists of user controls that again contain mostly simple controls like text boxes etc.
Both teams already signaled that they aren’t interested in MVC Sharp. These are the reasons:
- There is a lot of bioler plate code to be written
- The structure is not that straight forward
- The team currently using that MVC Sharp is also not completely convinced about that tool.
As a result we have been pretty open to better solutions that may be applied to all of the products to evolve to an unified approach for all the them.
First thoughts went into the direction of MVP that is highly event driven. What are the pros and cons? Surely there are some discussions out there, so I don’t have to do a deep dive into that:
What do I miss in these discussions?
Back in 2006 I started to do a MVC implementation on my own. This was also based on WinForms which was quite current shiny UI back then. I didn’t care about Dependency Injection there, and I had a certain perspective what kind of problems this framework shall solve.
As a result of that implementation, I recognized that I still had to write a lot of boiler plate code. This code surely was much better structured and also much more maintainable, extensible. But it was a lot to write.
And we wanted to increase all of the dimensions, right? Better maintainability, better extensibility, better understandability… and certainly having it faster.
To be honest, sure it was faster, but what tortured me was the fact that there are a lot of repetitive tasks. Developers automate. Developers don’t repeat themselves. (btw: Try this at home when having children :-D). What was missing?
As the discussion went on for finding the right approach, I thought about, what would be the minimum thing to do when using MVC? What would make me happy?
- We use a lot of libraries that make use of a fluent interface. FluentValidation, FluentNHibernate to name just two. Why? Because the readibility of fluent interfaces is much higher, and it is really easy to enhance.
- I don’t to write the code for making my model notify the other components about changes. This is most boring part. There are some tools out there for just accomplishing that task like the excellent Fody.
- I would like to be able to validate and react on the results
- I would like to react on changes that I can make controls visible or invisible.
- I don’t want to write the boiler plate code that passes a value from a model to the actual control and back
How would I like to write that code? I made a simple sample. Have a look at github mvcify repository.
Keep in mind, this is an early state and it is a prototype/ PoC for proving that the concept can work. This is far away from production code.
Let’s have a look onto this:
_dataBinder.Bind(txtName, simpleModel, model => model.Name) .Validate(model => SimpleFormController.ValidateName()) .OnSuccess(model => errorProvider1.Clear()) .OnFailed((model, ex) => errorProvider1.SetError(txtName, ex.Message));
What does it mean?
- There is a databinder in place.
- I do have an instance of “SimpleModel”
- There is a text box control that is called txtName
- There is the SimpleFormController providing validation rules
What is going to be accomplished?
- This obviously is a fluent interface
- It enables me to define how a certain value in my model can be bound to a certain piece of user interface. In the case above the Name property of the SimpleModel instance will be bound to txtName control which obviously is a textbox instance
- It also allows me to define validation rules. In this case, the logic of how a name property is evaluated is in the controller – as the business logic should not belong to a form. Additional the fluent interface allows be to define OnSuccess and OnFailed methods to react on the result of validation.
There are pieces that are discussable.
- In my sample this code is placed inside of the form.
- The validation rules are in controller.
- The controlling instance is called controller, not presenter.
- I just defined a “model”, no viewmodel.
- The interaction between model, view and controller is not specific enough.
- Keep in mind, this is work in progress
- What about button clickes?
- What about changes on the user interface as part of another change. Concretely when a checkbox is checked, show another user control?
- Is this an approach that could be feasible to grid control and treeview/ treegrid, grouping grids etc?
I do like this approach, but it has one main disadvantage. To make it that simple, there must be some kind of databinder that allows specific binding of specific controls.
But, to be honest.
Maybe it is worth the price to have the code
- highly readible
- best maintainance
- easy extensibility
- and last but not least: When there is a certain framework available that contains most of the controls that are going to be used… it is lightning fast to develop winforms.
This article now is long enough – there will be some more about exactly that topic.
Excellent Article… I was stumbling over the nuts and bolts of choosing the right way to implement more complex databound functionality in WinForms recently. Finding good information about doing such tasks in WinForms is not that easy or completly outdated, although WinForms is still more in uses than people think. I ended up with a mixture of MVP/MVVM/MVC and in certain situations even with databinding, but I’m not completly happy with it. Will overthink some code after your article and looking forward seeing your next one.
Thanks Jan! Will stay tuned on that topic, as there is still a strong need for this kind of functionality in WinForms from my point of view also. 🙂