Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

ASP.NET PropertyGrid User Web Control

4.95/5 (12 votes)
5 Feb 2013CPOL6 min read 47.6K   831  
ASP.NET enhanced PropertyGrid control connecting to any class.

Introduction

ASP.NET lacks a WebForm based Property Grid control which allows direct modification of objects honoring their component model attributes. Third party or open source contributions seem too clunky or just poorly implemented. While developing a custom framework recently I found myself needing to instrument quite a few ASP.NET web pages that manipulated my business objects. I did not have a lot of time to manually craft these pages to fit the unique requirements of my business objects, so I opted to spend a few hours to write an ASP.NET web based Property Grid kind of user control. I primarily wanted the user control to interrogate a single object dynamically, building the necessary HTML input tags required to read and manipulate the public properties of a class. This control is not perfect and there is plenty of room for improvement.

Image 1

Details

OK, first things first: How does this User Control speed up web page development? Typically building web pages that collect user input and applies this input to a backend database is very time consuming. Labels, various input controls, formatting, conditional display or read/write behavior, etc… take time to implement. And, various CRUDL ([C]reate [R]ead [U]pdate [D]elete [L]ist) functions may span a multitude of pages, or in some sad situations may be all jammed into one overly complex web page. We typically have to a lot of tedious work just to read data from, push new data to or update existing data in a database. Also, if an object changes, the web page(s) that invoke that object must change too. I am a firm believer of keeping database select statements and store procedure calls out of the user interface markup, instead using middle tier (Business Objects) to handle database activities. The Object Web Editor is capable of interrogating an invoked class , reading its component model attributes, rendering the Name of Properties, as well as the most appropriate Input User Control, “on the fly” as well as collecting and applying PostBack data to the object for further disposition. This significantly decreases the amount of HTML form work required allowing web pages to be implemented quickly. Also, a pleasant side effect of this user control is pages are implemented consistently.

The Microsoft System.ComponentModel namespace provides the means of marking up a class in such a way that object meta data will contain design-time/run-time “rules” for engaging and object instance of a given class. At the heart of the Object Web Editor is its ability to recursively Reflect into an object instance reading each property detecting its data type and providing the proper access based in property designer attributes.

Let us take a peek at how this user control is used on a web page and what it does when the page is loaded. Below is a screenshot of a simple web page of which invokes a Person class in its code-behind.

Image 2

Here we see the dynamically created HTML rendered by the Object Web Editor and the left, and the design-time view of the ASP.NET web page and code-behind on the right. I opted not to spend a lot of time on the design-time rendering and editing aspects of this User Control so there is no design-time rendered HTML or related property editor. The web page defines the following in its markup…

XML
<owe:ObjectWebEditor
id="personEditor"
runat="server"
ViewStateMode ="Enabled"
HiddenProperties="Exceptions" >
<owe:PropertyMap
PropertyName="HomePage"
LinkDescription="My Home Page" 
URL="MyHomePage.aspx?SSN={SSN}" 
ToolTip="Visit my Home Page" />
</owe:ObjectWebEditor>

I will cover the not-so-obvious properties of this custom user control.

HiddenProperties – This string contains a coma-delimited list of object properties that you do not wish to show. “Show” meaning, dynamically generate HTML to allow viewing and possibly editing of these properties. In the example above, I have excluded the Exceptions property of the underlying Person class. Defined within the ObjectWebEditor user control are child controls that provide custom handling of certain properties. In the example below, I have opted to exchange the normally rendered HTML associated with the “HomePage” property of the Person class with a hyperlink bearing the name “My Home Page”.

Image 3

Default.aspx invokes an instance of the Person class and the SelectedObject property of the ObjectWebEditor user control is set to this instance. Upon Page Load, ObjectWebEditor interrogates the Person object rendering the HTML necessary to display its properties. The editor honors component model attributes such as ReadOnly as well as only generates HTML for its public members.

Image 4

The Category attributes of class properties serve as section headers. These happen to be rendered in the order in which that are encountered during object interrogation.

Image 5

Entire categories can be hidden similarly to properties by defining Category Names in the HiddenCategories property of the ObjectWebEditor.

Image 6

Notice below how a few HTML input fields are grayed out. This is because these properties are marked read-only at the Activity class level. That does not mean one cannot programmatically change them.

Image 7

HTML markup was generated automatically and on-the-fly by the Object Web Editor user control. Each of the HTML input fields are named in such a way the Object Web Editor user control can determine where to apply a submitted value when a Post Back occurs. The table row containing the Description property HTML markup is shown below.

XML
<tr
class="PropertyGridPropertyRow"
align="left">
<td
class="PropertyGridPropertyName"
valign="top"
align="left"
width="100%">Age</td>
<td
class="PropertyGridPropertyValue"
valign="top"
align="left"
width="100%">

<input
id="personEditor_2"
name="personEditor_2" 
type="Text"
value="52" >
</td>
</tr>

Each HTML input field name combines the name of the Object Web Editor control plus the count of the property being represented. This guarantees each HTML input field to be unique no matter of the number of these controls that exist on a given page.

Upon post back the ObjectWebEditor  accesses the Request Form fields collection and matches up file names to its internal mapping of form field names to Selected Object class properties. It should be able to do this. After all, it created these fields in the first place ;o)

Some classes may contain instances of other classes as public properties. The ObjectWedEditor handles this by  invoking a new instance of itself and attaching it to the property…effective becoming its editor. Even then, the ClientID of this new user control instance is made unique by combining the ClientID of its parent “editor” in this case with “X” resulting in “editorX”. And if the hypothetical child class had  another child class, the same would be done again resulting in “editorXX” and so on.

There are situations in which one may want to hide on-the-fly generated HTML markup for one or more Properties. This is accomplished though the HiddenProperies property of the Object Web Editor user control.

HiddenProperties="Exceptions,ActivityStatus,ActivityType,Prerequisites"

The same is true for class categories.

HiddenCategories="System"

There are situations in which the actual name of a given property is not suitable for user interface display. In the example below we are changing the “LastName” displayed label to “Persons Last Name” using a nested PropertyMap definition.

Image 8

JavaScript can be placed within the URL Property of the PropertyMap definition in order to cause other dynamic run-time behavior to occur.

Image 9

The PropertyMap control can also substitute tokenized values with a named property value of the Selected Object. Here we see Person.SSN being applied to a URL…

Image 10

Each of the Object Web Editor user control resulting HTML table elements can be styled as follows:

CSS
.PropertyGrid
{
}

.PropertyNestedGrid
{
}

.PropertyGridCategory
{
    white-space: nowrap;
}

.PropertyGridCategoryName
{
    white-space: nowrap;
    font-weight: bold;
}

.PropertyGridPropertyRow
{
    white-space: nowrap;
}

.PropertyGridPropertyName
{
    white-space: nowrap;
}
.PropertyGridPropertyValue
{
    white-space: nowrap;
}

.PropertyGridPropertyLink
{
    white-space: nowrap;
}

For me the ObjectWebEditor user control significantly shortens ASP.NET web page development by providing dynamically generated presentation and data gathering HTML for a large percentage of the pages I work with these days. Using this control, I was able to churn out 20 web pages wrapping business objects in about one half of an hour opposed to taking a day building them by hand. Additionally, these pages ended up looking very uniform in the ASP markup as well as the code behind.

History

  • 1/2/2012: Initial release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)