Oftentimes, user controls mark regions or specific areas in
a page. The reason to do this is to reduce the amount of code involved; instead
of two pages duplicating the same code, the application can use user controls
to move the interface markup into a single area. However, often user controls
have to talk with other user controls in the page, or the page needs to work
with user controls. This poses a dilemma; how does that happen in the
dynamically compiled model?
The key is using one of two approaches: interfaces, or
custom user control classes. Let us look at the first option. Defining an
interface for the user control can make it easier to work with the control. Let
us look at an interface.
Listing 2
public interface IUserInfoControl
{
string FirstName
{
get;
}
string LastName
{
get;
}
string AddressLines
{
get;
}
string City
{
get;
}
string State
{
get;
}
string ZipCode
{
get;
}
}
This interface, when defined within a user control, exposes
the data that it holds. Alternatively, it could have exposed direct references to
the controls, if preferred. Either could work, but I like having a more
abstract interface, and by not exposing the controls directly, helps create a
more maintainable solution (if the controls that represent the user control
change, this interface does not have to).
So an ASP.NET User Controls code-behind can define this
interface as such:
Listing 3
public class MyUserControl: UserControl, IUserInfoControl
{
public string FirstName
{
get
{
return txtFirstName.Text;
}
}
public string LastName
{
get
{
return txtLastName.Text;
}
}
. .
}
Note that setters could have been included as well, which is
useful especially if data is loaded from a database, XML, or some other source.
So the page that hosts this can make use of the user control. But the page
could have done that anyway, since it has a direct reference to the control. So
where is the benefit?
The benefit lies if you need to leverage any coding in a
custom page class, such as making the page the sole driver for all the
interactions. This custom page class can make references to the user interface
and work with it as such. The custom page class approach is great if you have a
common user control used throughout the application, or if you have two pages
that have mostly the same code, but work slightly differently (such as an add
and edit page).
The custom page class can work with the interface in an
abstract manner, by exposing an abstract property that the ASP.NET code-behind
file will implement.
Listing 4
public class UserRegistrationPage : Page
{
public abstract IUserInfoControl UserInfo { get; }
}
The ASP.NET code-behind file overrides the property and
returns an instance of the control that exists in the page. This is necessary
because the custom page class knows nothing about the actual implementation,
and by not doing it this way, the custom page class knows nothing about the
User Info control.
Listing 5
public class ASPXRegistrationPage : UserRegistrationPage
{
public override IUserInfoControl UserInfo
{
get { return this.wucUserInfoControl; }
}
}
The custom page class can then work with the user info
control data in any way that it desires. For instance, it could define code to
work with the data below:
Listing 6
public class UserRegistrationPage: Page
{
public void GetUserInfo()
{
UsersTableAdapter adapter = new UsersTableAdapters.UsersTableAdapter();
UsersTable table = adapter.GetUserInfo(User.Identity.Name);
if (table != null && table.Rows.Count > 0)
{
UsersRow row = (UsersRow)table.Rows[0];
this.UserInfo.FirstName = row.FirstName;
this.UserInfo.LastName = row.LastName;
. .
}
}
public void SaveUserInfo()
{
UsersTableAdapter adapter = new UsersTableAdapters.UsersTableAdapter();
UsersTable table = new UsersTable();
UsersRow row = table.NewUsersRow();
row.FirstName = this.UserInfo.FirstName;
row.LastName = this.UserInfo.LastName;
. .
}
}
In this way, the custom page class can work with the user
control's information in a way that is useful to it.