ControlFreak
LANGUAGES:
C# | VB.NET | HTML
ASP.NET
VERSIONS: 1.0 | 1.1
Ease Control Positioning Headaches
HTML Allows Great Flexibility for Page Design, but All
the Options Can Be Overwhelming
By Steve C. Orr
You ve had problems with the WebForm designer in Visual
Studio.NET. I know you have. Controls have refused to go where you drag them,
or they show up in different places at run time than design time. Or maybe the
designer has chosen to reformat HTML that you ve carefully typed. In fact, I
don t know a single developer who would claim the HTML designer included with
Visual Studio.NET is the best one around but it s not the worst one, either. Once
you understand some key techniques, it s possible to become quite efficient
with it.
If you re background is centered more in Windows
development than Web development, you re likely more confused by the WebForm
designer than most. The simplicity of the Windows Forms designer is appealing
compared to all the complex options available in the WebForms design environment.
However, once you ve mastered the power that WebForms (and HTML) have to offer,
you ll be whining about why you can t design things so flexibly in Windows Forms
applications. Happily, Microsoft has made great strides in improving both the
WebForms and Windows Forms designers in the upcoming Visual Studio.NET 2005,
but you don t need to wait until then to develop great applications. This
article will help you get the most out of the current technology.
When a new Web application project is created in Visual
Studio.NET, a default WebForm is created. Notice the text immediately visible
in the center of this form. The text says, The page you are working on is in
grid layout mode, and objects will be arranged using absolute (x and y)
coordinates. To use flow layout (top to bottom, as in a word document), change
the pageLayout property of the document to FlowLayout. It s a message you ve
likely seen many times before, although it seems many developers haven t put
much thought into its meaning.
If you re from a Windows development background, you ll
find the default GridLayout mode to be familiar and intuitive. Quite simply, if
you drag a control to a pixel-specific position on your form, it will stay
there. You might wonder why anyone would ever want a behavior other than this. Well,
there are a few reasons why FlowLayout is often a better choice than
GridLayout.
Compatibility
The original HTML specification didn t allow for precise
placement of controls on a Web page. The whole concept was to let the content
of a page flow naturally to whatever dimensions the user s display allows. This
foundational feature of HTML is still in place today, and it is used by default
on a WebForm when the pageLayout property is set to FlowLayout. This adaptive
layout is quite appealing in many ways. For example, it empowers the Web
browser to make decisions about how best to display the content so you don t
have to worry about how the page will look on various devices at various sizes,
color depths, and resolutions. Therefore, it is virtually guaranteed that
content will always be displayed in a reasonable and useful way to the user. It
also allows you to dynamically output content of various sizes without worrying
about how it will affect other elements of your page. For example, if today s
article of the day is unusually long, the page height will automatically expand
and your page footer will appear underneath the article as you d expect.
However, some Web design artists are more interested in
pixel-perfect placement than they are with universal compatibility. It can be
quite annoying to finally get a control positioned just perfectly at design
time, only to see some errant Web browser choose to fix it by placing it
elsewhere. Pixel-perfect placement of Web page elements is one of the many
issues that Cascading Style Sheets (CSS) addressed when it was created, and
GridLayout is the ASP.NET technology that exploits it. It s the only practical
way to ensure a complex HTML page is displayed exactly as a graphic artist designed
it to look.
If you are in the fortunate position of being able to
presume all your users have a modern, fully functional PC-based Web browser,
then GridLayout can be a great tool. However, if you need to support a variety
of browsers and handheld devices, then you re probably better off sticking with
the more conventional FlowLayout approach. Figure 1 concisely describes the
pros and cons of both pageLayout options.
|
FlowLayout
|
|
Pros
|
Cons
|
|
Compatible with every Web browser and many handheld
devices.
|
Content may look decent, but you can t generally ensure
it will look great.
|
|
Content is dynamically positioned so it should always
look decent.
|
Hard to predict how the content will look to all your
users.
|
|
GridLayout
|
|
Pros
|
Cons
|
|
Simple concept based on x and y positioning.
|
Limited compatibility with handheld devices and older
browsers.
|
|
All content will display exactly where you ve specified.
|
Dynamic content can spill out of designated areas to
look ugly and unreadable if you re not careful.
|
Figure 1: GridLayout
and FlowLayout both are valid options, but neither are perfect for all
scenarios. Luckily, you can often mix and match them to get the best of both
worlds.
GridLayout Rendering Details
GridLayout is the default pageLayout property for every
WebForm in a new Visual Studio.NET Web application. Unfortunately, there is no
good way to change this default. However, once a new project has been created,
this default can at least be changed on a project-wide basis. To do this,
select Properties from the Project dropdown menu in Visual Studio.NET. Then
select Designer Defaults in the treeview on the left side of the dialog box (see
Figure 2). Flow or Grid can then be selected from the Page layout dropdown
list. From this point on, whenever you add a new WebForm to the project, it
will (by default) have the pageLayout property that you ve selected. (You can
still change the pageLayout on a page by page basis and have various pages that
use different layout modes, if you choose.)
Figure 2: When you start a new Web
application, you might want to adjust the default pageLayout property for your
WebForms so you won t have to make this tedious adjustment to each of them
individually.
If you drag a CheckBox Web control onto a blank WebForm
that is set to GridLayout mode, then run the project and view the resulting
HTML, you ll see this representation of the CheckBox:
<span style="Z-INDEX: 101; LEFT: 192px;
POSITION: absolute; TOP:
168px">
<input id="CheckBox1" type="checkbox"
name="CheckBox1"
/></span>
You ll notice that the CheckBox is placed inside a span
tag that is absolutely positioned at a specific pixel location using the LEFT
and TOP pixel coordinates. Additionally, a Z-INDEX is specified so you can
place controls on top of (or beneath) other controls. All this is great if the
user s browser supports it, but what happens if it doesn t? Well, ASP.NET is
fairly smart about such matters, and does its best to compensate if it detects
an older low-level browser. If ASP.NET suspects the browser may not be able to
handle CSS positioning, it instead outputs nested tables to approximate the
positioning you ve specified on your WebForm. That exact same checkbox will be
positioned with very different HTML if ASP.NET determines it to be necessary:
<TABLE height="189" cellSpacing="0"
cellPadding="0" width= _
"297"
border="0" ms_2d_layout="TRUE">
<TR
vAlign="top">
<TD
width="192" height="168"></TD>
<TD
width="105"></TD>
</TR>
<TR
vAlign="top">
<TD
height="21"></TD>
<TD>
<input
id="CheckBox1" type="checkbox" name= _
"CheckBox1"
/>
</TD>
</TR>
</TABLE>
As you can see, a whole table structure must be created
around the checkbox to attempt to position it in the appropriate place. If you
were designing a form in FlowLayout mode, there s a good chance you d manually
structure the page similarly to achieve the same layout. It can be convenient
for ASP.NET to automatically generate this code for you. In effect, you might
think of it as automatically converting a grid layout to more of a flow layout.
However, the result is sometimes less than perfect. On complex pages the
controls don t always end up being positioned exactly where you ve specified. Additionally,
it s not especially efficient code compared to the more concise CSS syntax, so
it s nice to avoid this kind of HTML output when you can. It s also nice to be
able to override ASP.NET s default decisions about when to render low-level
output. For this purpose, the targetSchema property of a WebForm can be used to
manually specify the flavor of HTML that is output. The Project Properties
dialog box discussed earlier (again, see Figure 2) allows you to set the
default targetSchema property for all new WebForms.
Precision Positioning: Be Careful What You Wish For
The beauty and the bane of GridLayout mode is that
controls are placed exactly where you specify. For example, let s take a basic Web
page with a banner at a top position of zero, a DataGrid placed near the center
200 pixels down, and a page footer near the bottom at pixel row 600. Tests show
the page to look great when the DataGrid has 10 rows, but when the DataGrid has
20 rows, it spills over the top of the footer beyond row 600, causing an ugly,
unreadable mess.
Because you re choosing exactly where you want the
controls, you now also need to control exactly how big they get or else you re
going to end up with various crowding problems such as this. It s the kind of
problem you re asking for when you choose GridLayout mode, and it is one of the
main reasons I usually choose FlowLayout for my WebForms. But don t be too
discouraged; there are usually some reasonable solutions if you re determined
to stick with GridLayout. For example, you can box a DataGrid inside a CSS overflow
area of a specified size so it will never take up more space on the page than
you ve specified:
<div style="OVERFLOW:auto;WIDTH:300px;HEIGHT:400px">
<asp:DataGrid
id="DataGrid1" runat= _
"server"></asp:DataGrid>
</div>
If the DataGrid grows bigger than 300x400 pixels, the HTML
above specifies that scroll bars will auto matically appear as needed so the
user will still have access to all the information contained within the grid. This
technique will work with virtually any page element, not only a DataGrid.
Go with the Flow
In the early days of ASP.NET, there was a bit of a
religious debate about which layout mode was better. In many ways, this is like
trying to decide if VB.NET or C# is better. (Answer: they are both better in
their own ways.) However, on the subject of page layout, the debate has died
down and the majority has spoken. These days most experienced ASP.NET
developers will tell you that FlowLayout is the way to go most of the time. Don t
get me wrong there s no doubt that GridLayout is very useful in many
situations, but it often feels a bit like trying to fit a square peg into a
round hole. It has a bolted-on-after-the-fact feeling to it because it was. The
beauty and strength of classic HTML (represented by FlowLayout) has always been
its ability to adapt content to a variety of Web browsers, screen sizes, and
related display devices. So if you re using the rigid GridLayout mode (which
was not originally supported in HTML), then you should recognize you re going
against the grain. Microsoft has recognized this shift in developer sentiment
and the result is that FlowLayout will be the new default pageLayout for
WebForms in ASP.NET 2.0.
With FlowLayout mode, you don t specify precise positions
for controls. You won t find any Top or Left properties, nor will you find
references to X, Y, or Z. Controls are placed relative to other controls. You
can specify that you want a textbox placed next to a label, or underneath a
label, but the browser will make the final decision on the precise positioning
based on the space available. Tables and Panels are often used to ensure sets
of related controls are grouped together. They are often used in complex
combinations, such as nesting a table inside the cell of another table. Common
sets of controls are often converted into user controls so they can be reused
on many pages within a project.
The HTML Table control (found on the HTML tab of the
Visual Studio.NET toolbox) is an excellent tool to use for positioning various
elements of a Web page at design time. You resize columns and rows with the
click of a mouse, drag and drop controls wherever you wish, and create new
table cells easily via the right-click menu. If you d like to be able to
interact with the table at run time, simply mark it with the RunAt = Server
attribute. If you only need to interact with specific rows or cells of the
table at run time, then you can mark only those elements with the RunAt =
Server attribute. This can be handy for hiding or highlighting page elements
dynamically.
Don t confuse the HTML Table control with the Table Web
control that s found in the Web Forms tab of the Visual Studio.NET toolbox. The
Table Web control is a bit weak at design time compared with its HTML control
counterpart, but it is a powerful tool for building page sections dynamically
at run time.
It should be noted that if you drop a control onto a
GridLayout WebForm and then switch the WebForm to FlowLayout, the control will
be a bit confused about how it should position itself. It will still have the
absolute positioning style elements in its HTML definition, and therefore may
not flow quite as you d expect. If you truly want the control to switch to
FlowLayout, you can go into the HTML view of the page and delete the
positioning style attributes. Alternatively, you can delete the control and
drag a new instance of the control onto the form in its place. This new control
will clearly see that the form is using FlowLayout and will conform without
hassles.
Why Be Choosey?
Don t stress out about which pageLayout mode to pick. You
can have the best of both worlds. On the HTML tab of your Visual Studio.NET
toolbox you ll find two often-ignored controls named Flow Layout Panel and Grid
Layout Panel. You can use either of these controls on any WebForm, regardless
of the WebForm s pageLayout property value. As you might have guessed, these
controls will let you have a GridLayout area inside a FlowLayout page, and
vice-versa. This can certainly be useful for leveraging the strengths (and
negating the weaknesses) of both techniques. When placing a control inside a
Grid Layout Panel, you should understand that the top-left position (0,0)
represents the top-left position of the Grid Layout Panel, not the WebForm. Therefore,
you could have many top-left positions in your page if you have many Grid
Layout Panels.
These special panel controls can also be useful when
designing your own Web controls, because you can use one to specify the
placement of your control s various elements using whichever layout technique
you prefer without regard to the pageLayout property of the hosting page.
Conclusion
In summary, although FlowLayout is usually the best
default for ASP.NET development, don t be afraid to switch to GridLayout when
you need it especially if wide compatibility is not a requirement. The
important things to understand are the benefits and drawbacks of the available
options, and how various techniques can be mixed together to accomplish any
design imaginable. Hopefully you now have a better understanding of these types
of control positioning details.
Steve C. Orr is an
MCSD and a Microsoft MVP in ASP.NET. He s been developing software solutions
for leading companies in the Seattle
area for more than a decade. When he s not busy designing software systems or
writing about them, he can often be found loitering at local user groups and
habitually lurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.net
or e-mail him at mailto:Steve@Orr.net.
Position Controls Created at Run Time
Q: How do I position
controls that are created at run time?
A: After instantiating the control, add it to the control
collection of a container control that exists at design time, such as a Panel,
TableCell, or PlaceHolder. The PlaceHolder control is often the best choice in
such a situation because this is the main purpose of its existence. A
PlaceHolder control allows you to define a position for a control (or set of
controls) at design time, even though the controls themselves won t exist until
run time. Maybe you don t even know what kind of control will be created, but
you can still define its future placement. Here s a code snippet to give you
the basic idea:
(VB.NET)
Dim Btn As HtmlButton = New HtmlButton
Btn.InnerText = "Click Me"
PlaceHolder1.Controls.Add(Btn)
(C#)
HtmlButton Btn = new HtmlButton();
Btn.InnerText = "Click Me";
PlaceHolder1.Controls.Add(Btn);