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).
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 pasted one of the test cases I used to build this class below.
It is written with NUnit/C#, so hopefully, it should at least be readable to everyone:
[Test]
public void MultiPanelAdds()
{
Panel PanelA = new Panel();
Panel PanelB = new Panel();
Panel PanelC = new Panel();
TextBox TextBoxA = new TextBox();
ViewManager MyViews = new ViewManager();
MyViews.Add("View AB", PanelA);
MyViews.Add("View AB", PanelB);
MyViews.Add("View AB", TextBoxA);
MyViews.Add("View AC", PanelA);
MyViews.Add("View AC", PanelC);
Assert.IsFalse(PanelA.Visible, "PanelA should be hidden.");
Assert.IsFalse(PanelB.Visible, "PanelB should be hidden.");
Assert.IsFalse(PanelC.Visible, "PanelC should be hidden.");
Assert.IsFalse(TextBoxA.Visible, "The textbox should be hidden.");
MyViews.SetActiveView("View AB");
Assert.IsTrue(PanelA.Visible, "PanelA should be visible.");
Assert.IsTrue(PanelB.Visible, "PanelB should be visible.");
Assert.IsTrue(TextBoxA.Visible, "The textbox should be visible.");
Assert.IsFalse(PanelC.Visible, "PanelC should be hidden.");
MyViews.SetActiveView("View AC");
Assert.IsTrue(PanelA.Visible, "PanelA should be visible.");
Assert.IsFalse(PanelB.Visible, "PanelB should be hidden.");
Assert.IsFalse(TextBoxA.Visible, "The textbox should be hidden.");
Assert.IsTrue(PanelC.Visible, "PanelC should be hidden.");
}
All of the Assert
s are for testing purposes only. First, I basically instantiate some panels that my test will use. Normally, you wouldn't explicitly instantiate these, and my class does not require it either. Next, I instantiate my ViewManager
. Adding a view is as simple as passing the ViewManger
your view name and the object you want to be a part of that view.
Points of Interest
The class itself leverages a Dictionary
object which contains the keys associated with the 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.
History
I may add the ability for the class to have multiple views visible simultaneously. I may just wait to see what the feedback is before doing that however.