| Scenario one: |
Have a shared ASPX page that must display the same controls laid out horizontally vs vertically |
| |
The intent here is to determine how realistic it is to use a shared partial class with different UI layouts.
Currently you can easily handle this by dynamically loading a different control to the page and ensuring that the
control is completely self-aware. The control gets the data/manipulates it, etc. |
| |
For this example I wanted to have the shared code beside handle all the page logic. I didn't want to have to
have duplicate code in the controls. |
| |
I setup my web page [AddUserThree.aspx] using a simple MasterPage [MasterPage_Custom.master]:
<asp:ContentPlaceHolder ID="pageBodyContentPlaceHolder" Runat="Server">
</asp:ContentPlaceHolder>
I then moved the click event from the user control to AddUserThree.aspx.cs. This doesn't work. Since the code in the
code beside isn't compiled there is no way to reference from one to another (that I could figure out anyway).
Okay, I thought, no problem. I added an event declaration to the user control [AddNewUser.ascx]. Again I had the same
problem. The public delegate for the event wasn't visible outside of the page.
I moved the delegate declaration to a class in the /code folder. This folder contains classes that are generally available
to the web site. My delegate was suddenly visible.
|
Next step was to attached the AddUserThree.aspx page to the event in the user control. Once again code beside foiled me. The declaration of the event inside
the user control wasn't visible.
I came up with a couple of options:
- Create a base user control and have all my shared controls inherit from it
- Create an interface and have all my shared controls implement it
A quick attempt at the base page produced a number of nasty errors. The issue being that the partial classes inheritance didn't match.
This makes sense because all I changed was the partial class that was visible to me in the IDE. I'm going to assume that there is a way to
change the inheritance of the partial class, but I punted on that approach and went with the interface.
|
I created a simple interface that contains the one method whose event I wanted to bubble up:
public interface IAddNewUser
{
event NewUserEventHandler OnNewUserClick;
void AddUser_Click(object sender, EventArgs e);
}
|
Next step was to implement that interface in my user control(s) partial class
public partial class AddNewUser_ascx : IAddNewUser
{
public event NewUserEventHandler OnNewUserClick;
public void AddUser_Click(object sender, EventArgs e)
{
if(OnNewUserClick!=null)
OnNewUserClick();
}
}
|
The final step was to hook the aspx into the event
public partial class AddUserThree_aspx
{
#region OnPreInit
/// Load up the correct user control based upon querystring parameter
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
object pageType = Request.QueryString["PageType"];
int controlID = 1;
if(pageType !=null)
{
controlID = Convert.ToInt32(pageType);
}
LoadCustomControl(controlID);
}
#endregion
#region LoadCustomControl
/// Load the control specified by the controlType
private void LoadCustomControl(int controlType)
{
//get a reference to our placeholder
Control ctr = this.Master.FindControl("pageBodyContentPlaceHolder");
string controlPath;
//the LoadControl is defined for us in TemplateControl abstract class
switch (controlType)
{
case 1:
controlPath = @"~/AddNewUser.ascx";
break;
case 2:
controlPath = @"~/AddNewUser2.ascx";
break;
default:
throw new InvalidOperationException("Unable to load a control based upon type " + controlType.ToString());
}
Control loadedControl = LoadControl(controlPath);
((IAddNewUser)loadedControl).OnNewUserClick += new NewUserEventHandler(AddNewUserClick);
ctr.Controls.Add(loadedControl);
}
#endregion
#region AddNewUserClick
void AddNewUserClick()
{
if (!Page.IsValid)
{
Page.Title = "Warning Page isn't valid";
}
}
#endregion
}
|
| |
At this point I can define any events in my interface and as long as the controls implement that interface I can
capture them and respond as needed. My initial take on these effort is that partial classes, while offering a lot, change the way you have to approach
your problems. It seems likely that this is going to break a fair amount of code that exists today under the 1.1 framework.
|
| My goal in this scenario was to try and test a shared code beside between the user controls. It turned out that I couldn't get that to work, so I moved that shared
logic into the page that was hosting the shared controls and added custom events to get the scenario working. Next step is to try the same thing but using a Dynamically loaded master page.
|