I'm trying to figure out how MVP should be implemented at the UserControl
level. I thought I had it, but I ended up reading a blog post that pretty much shut me down. Now I'm back at the start and with no idea how to proceed.
Let's say my UserControl
is something simple like two TextBox
es and a ComboBox
. This gets invoked from a main form (which has its own View and Presenter). Now, the way I understand MVP is that the Main Form Presenter is supposed to invoke a second presenter to handle all communication with the UserControl that gets dropped there.
And this is where I get completely lost. My past implementations of UserControl
s (before I learned MVP) always incorporated the logic behind the control (e.g. ComboBox
selection will change text label related to TextBox1
). As such, implementation of the UserControl
is done by dragging it onto the designer, and then calling commands like UserControl1.Update()
or UserControl1.DisplayData(data)
.
In any third-party UserControl
, all commands to the UserControl
are performed by commands to the control. There is no "presenter" that needs to be invoked, for instance, when I drop a ComboBox
, or a ListView
, or any other WinForms control onto my form. Yet they have internal logic that dictates how they display, and in the essence of testing, it should have a "presenter" separation to it somewhere.
I thought that a good solution would be that the constructor of my UserControl
would create a Presenter. Any commands to the UserControl
would delegate straight to the Presenter. This would allow my UserControl
to have its own presentation logic separated from its "view", such that I can test it, and such that the implementer (the Main Form) need only drop in the UserControl
and perform data sends and receives as part of its local presentation logic. The UserControl
has its own presentation logic left invisible to the implementer.
And just when I thought I understood it all, I find out that it's bad practice (The Self-Aware View). So I plead with people who understand this better than I: How do I construct a UserControl
that keeps its presentation logic invisible to the end-user, such that I don't have to construct the wrapping presenter in my Main Form, without violating the principles that Matt Wynne discusses in the linked post above?
Or am I completely misunderstanding the concept of MVP here?
Best Answer
I read through Matt Wynne's blog entry that you linked, and I can see where some of the confusion is coming from. So let's point out a few differences between his article and your situation.
Your question was asked on Aug 21st of 2013. Matt's article was published on June 13 of 2007.
You tagged your question with c# and winforms, although I think you meant wpf instead of winForms. Matt states his focus and experience has been with ASP.NET.
I want to point out that we're already at a) dated advice and b) differing UI technologies.
ASP.NET and the
MV*
pattern(s) it supports have changed significantly since then. Likewise, users of Silverlight and WPF have since generated a lot of guidance with using theMVVM
pattern and data binding.And as a point of reference, I would recommend reading over Martin Fowler's articles on Passive View and Supervising Controller which are the patterns he broke out from his original MVP pattern.
I think your question is more interesting when looking at the broader point of view and asking "what does
MV*
help me with for a framework?" And the primary driver of this family of patterns is to encapsulate the areas that are likely to change. Related to that encapsulation is the single responsibility principle and making sure each component owns what it should.We encapsulate all of the view logic in the
View
layer so we can more easily change out our UI technology at an appropriate point later on in time. Likewise with theModel
and whatever you choose to use with the middle layer.So the answer to your question is to put the appropriate view logic within that layer to make your technology work. If you're using winForms, you'll end up with a lot of code-behind in order to make the form work. WPF supports data binding and significantly reduces the amount of code-behind. The logic you put in the
View
should potentially go away when you change UI technologies.Likewise, if you have presentation rules that are not imposed by the UI technology then you'll put those rules in your middle layer as they need to persist into your next UI.
I don't mean to diminish the fact that there are differences between the
MV*
patterns, and those differences exist for good reason. But their development was driven by the needs of particular technologies. You're using potentially different tech, so use theMV*
pattern appropriate for your environment. The frameworks are there to facilitate future change, not handcuff your current development.