Introduction
In this article, I will be showcasing a class I created called the ViewManager
. It basically allows you to add any control to its internal lists of views and their associated controls. It's best used on web forms that leverage multiple views (such as forms that have a different look for each different user role, or, as in the example, managing more complex view/edit views). One of the key things this tool can do that others can't is it allows you to place the same control into multiple views. It also allows you to easily and quickly maintain your views from one central place within your code.
Background
Where I work, I frequently run into code that is managing the visibility of many objects at a time. Essentially, the web forms try to give the illusion that they are two or three different pages when they are actually only one page. I personally would rather see these pages be separate pages, but I need an intermediate step that I can use for my refactoring (the code-behind can easily run over a thousand lines of code, so I like to take smaller steps so that my testing can be more thorough).
So what can I do? I can use panels or view controls. View controls have a slight edge to panels in terms of view management, but what about if some controls belong to multiple views? What if the controls that make up my views are interspersed? Enter my tool, the ViewManager
class.
Using the Code
OK, so you have the class, but how do you use it? So often you see these classes given by other programmers and they do so much and leave so much for you to think about that they are virtually useless. I'm going to try my best to break it down as simply as possible.
In the example project, this is how I am changing to edit mode and to the read-only mode:
protected void EditButton_Click(object sender, EventArgs e)
{
MyViewManager.SetActiveView(EditCustomerViewName);
}
protected void SaveButton_Click(object sender, EventArgs e)
{
MyViewManager.SetActiveView(ViewCustomerViewName);
}
EditCustomerViewName
and ViewCustomerViewName
are string variables which hold the name of each respective view. I made them into global variables available throughout my Page
class so different methods could access the same names without duplicating the strings.
The most complicated part is associating each view with its child controls. This is how I did that. I'll show you the way I associated the edit controls first.
protected void InitializeViews()
{
MyViewManager = new ViewManager();
List<Control> EditableCustNames = new List<Control>();
EditableCustNames.Add(FirstNameField);
EditableCustNames.Add(MiddleInitialField);
EditableCustNames.Add(LastNameField);
MyViewManager.Add(EditCustomerViewName, SaveButton);
MyViewManager.Add(EditCustomerViewName,EditableCustNames);
I created a method called InitializeViews
. This gives me a central place where I can set up my ViewManager
(which is also globally accessible to the Page
class). The next thing I do is create a list of controls. I do this just to logically group controls together. In this example, each of the controls in that list is a control used to edit the customer's name. You do not have to add your controls via lists. There is also an overload to handle assigning controls in a piece-wise fashion to each view, as we see on the last line in the example.
Once again, I'd like to stress that EditCustomerViewName
is no more than a string. I could have just as easily replaced the variables with the actual string "Edit Customer"
. The reason I chose to use variables is because spelling is critical. Views are not strongly typed so you will not know of any errors until runtime. So once again I stress, type your view names in one spot in your code (or use structs) and reference via the variable names so it is strongly typed.
That's basically it. You can also remove views if you desire it. I haven't done that in this example, but it is as easy as calling MyViewManager.RemoveView(EditCustomerViewName)
.
Points of Interest
The class itself leverages a Dictionary
object which contains keys associated with strongly typed List
s (List<Control>
). Luckily, C# maintains a reference between the controls all the way down to the lists so that a change to a control in one of the lists is as good as a change to the control itself.
One other side note...
Upon being added to a view, a control's Visible
property is set to false
. Basically, if you don't explicitly set a view as active, the view is assumed to be inactive. Another caveat is that only one view may be active at a time. Given the ability to overlap controls into multiple views, that shouldn't be a limiting factor, but it is mentioned just so that you can be aware of the class' assumptions.
And one other...
I wrote this much more thorough article due to a comment on a much briefer article. The original article was only intended for Intermediate to Advanced developers as I used a unit test to document the code and expected the developer to use that to his/her advantage. I hope this will help more of you to use this great tool.
History
- Created this article due to a comment posted here: Complete Control Over Views.
- Added more info to the introduction regarding the benefits of the class.