ControlFreak
LANGUAGES:C# | VB.NET | HTML
ASP.NETVERSIONS: 1.0 | 1.1
Ease Control Positioning Headaches
HTML Allows Great Flexibility for Page Design, but Allthe Options Can Be Overwhelming
By Steve C. Orr
You?ve had problems with the WebForm designer in VisualStudio.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 thedesigner has chosen to reformat HTML that you?ve carefully typed. In fact, Idon?t know a single developer who would claim the HTML designer included withVisual Studio.NET is the best one around ? but it?s not the worst one, either. Onceyou understand some key techniques, it?s possible to become quite efficientwith it.
If you?re background is centered more in Windowsdevelopment than Web development, you?re likely more confused by the WebFormdesigner than most. The simplicity of the Windows Forms designer is appealingcompared 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 Formsapplications. Happily, Microsoft has made great strides in improving both theWebForms and Windows Forms designers in the upcoming Visual Studio.NET 2005,but you don?t need to wait until then to develop great applications. Thisarticle will help you get the most out of the current technology.
When a new Web application project is created in VisualStudio.NET, a default WebForm is created. Notice the text immediately visiblein the center of this form. The text says, ?The page you are working on is ingrid 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), changethe pageLayout property of the document to FlowLayout.? It?s a message you?velikely seen many times before, although it seems many developers haven?t putmuch thought into its meaning.
If you?re from a Windows development background, you?llfind the default GridLayout mode to be familiar and intuitive. Quite simply, ifyou drag a control to a pixel-specific position on your form, it will staythere. 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 thanGridLayout.
Compatibility
The original HTML specification didn?t allow for preciseplacement of controls on a Web page. The whole concept was to let the contentof a page flow naturally to whatever dimensions the user?s display allows. Thisfoundational feature of HTML is still in place today, and it is used by defaulton a WebForm when the pageLayout property is set to FlowLayout. This adaptivelayout is quite appealing in many ways. For example, it empowers the Webbrowser to make decisions about how best to display the content so you don?thave to worry about how the page will look on various devices at various sizes,color depths, and resolutions. Therefore, it is virtually guaranteed thatcontent will always be displayed in a reasonable and useful way to the user. Italso allows you to dynamically output content of various sizes without worryingabout how it will affect other elements of your page. For example, if today?sarticle of the day is unusually long, the page height will automatically expandand your page footer will appear underneath the article as you?d expect.
However, some Web design artists are more interested inpixel-perfect placement than they are with universal compatibility. It can bequite annoying to finally get a control positioned just perfectly at designtime, only to see some errant Web browser choose to ?fix? it by placing itelsewhere. Pixel-perfect placement of Web page elements is one of the manyissues that Cascading Style Sheets (CSS) addressed when it was created, andGridLayout is the ASP.NET technology that exploits it. It?s the only practicalway to ensure a complex HTML page is displayed exactly as a graphic artist designedit to look.
If you are in the fortunate position of being able topresume 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 varietyof browsers and handheld devices, then you?re probably better off sticking withthe more conventional FlowLayout approach. Figure 1 concisely describes thepros 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: GridLayoutand FlowLayout both are valid options, but neither are perfect for allscenarios. Luckily, you can often mix and match them to get the best of bothworlds.
GridLayout Rendering Details
GridLayout is the default pageLayout property for everyWebForm in a new Visual Studio.NET Web application. Unfortunately, there is nogood 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. Thenselect Designer Defaults in the treeview on the left side of the dialog box (seeFigure 2). Flow or Grid can then be selected from the Page layout dropdownlist. From this point on, whenever you add a new WebForm to the project, itwill (by default) have the pageLayout property that you?ve selected. (You canstill change the pageLayout on a page by page basis and have various pages thatuse different layout modes, if you choose.)
Figure 2: When you start a new Webapplication, you might want to adjust the default pageLayout property for yourWebForms so you won?t have to make this tedious adjustment to each of themindividually.
If you drag a CheckBox Web control onto a blank WebFormthat is set to GridLayout mode, then run the project and view the resultingHTML, 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 spantag that is absolutely positioned at a specific pixel location using the LEFTand TOP pixel coordinates. Additionally, a Z-INDEX is specified so you canplace controls on top of (or beneath) other controls. All this is great if theuser?s browser supports it, but what happens if it doesn?t? Well, ASP.NET isfairly smart about such matters, and does its best to compensate if it detectsan older ?low-level? browser. If ASP.NET suspects the browser may not be able tohandle CSS positioning, it instead outputs nested tables to approximate thepositioning you?ve specified on your WebForm. That exact same checkbox will bepositioned 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">
<TRvAlign="top">
<TDwidth="192" height="168"></TD>
<TDwidth="105"></TD>
</TR>
<TRvAlign="top">
<TDheight="21"></TD>
<TD>
<inputid="CheckBox1" type="checkbox" name= _
"CheckBox1"/>
</TD>
</TR>
</TABLE>
As you can see, a whole table structure must be createdaround the checkbox to attempt to position it in the appropriate place. If youwere designing a form in FlowLayout mode, there?s a good chance you?d manuallystructure the page similarly to achieve the same layout. It can be convenientfor ASP.NET to automatically generate this code for you. In effect, you mightthink 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 thecontrols 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, soit?s nice to avoid this kind of HTML output when you can. It?s also nice to beable to override ASP.NET?s default decisions about when to render low-leveloutput. For this purpose, the targetSchema property of a WebForm can be used tomanually specify the flavor of HTML that is output. The Project Propertiesdialog box discussed earlier (again, see Figure 2) allows you to set thedefault targetSchema property for all new WebForms.
Precision Positioning: Be Careful What You Wish For
The beauty and the bane of GridLayout mode is thatcontrols are placed exactly where you specify. For example, let?s take a basic Webpage with a banner at a top position of zero, a DataGrid placed near the center200 pixels down, and a page footer near the bottom at pixel row 600. Tests showthe page to look great when the DataGrid has 10 rows, but when the DataGrid has20 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 thecontrols, you now also need to control exactly how big they get or else you?regoing to end up with various crowding problems such as this. It?s the kind ofproblem you?re asking for when you choose GridLayout mode, and it is one of themain reasons I usually choose FlowLayout for my WebForms. But don?t be toodiscouraged; there are usually some reasonable solutions if you?re determinedto 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 thanyou?ve specified:
<div style="OVERFLOW:auto;WIDTH:300px;HEIGHT:400px">
<asp:DataGridid="DataGrid1" runat= _
"server"></asp:DataGrid>
</div>
If the DataGrid grows bigger than 300x400 pixels, the HTMLabove specifies that scroll bars will ?auto?matically appear as needed so theuser will still have access to all the information contained within the grid. Thistechnique 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 areligious debate about which layout mode was better. In many ways, this is liketrying to decide if VB.NET or C# is better. (Answer: they are both better intheir own ways.) However, on the subject of page layout, the debate has dieddown and the majority has spoken. These days most experienced ASP.NETdevelopers will tell you that FlowLayout is the way to go most of the time. Don?tget me wrong ? there?s no doubt that GridLayout is very useful in manysituations, but it often feels a bit like trying to fit a square peg into around hole. It has a bolted-on-after-the-fact feeling to it ? because it was. Thebeauty and strength of classic HTML (represented by FlowLayout) has always beenits ability to adapt content to a variety of Web browsers, screen sizes, andrelated display devices. So if you?re using the rigid GridLayout mode (whichwas not originally supported in HTML), then you should recognize you?re goingagainst the grain. Microsoft has recognized this shift in developer sentimentand the result is that FlowLayout will be the new default pageLayout forWebForms in ASP.NET 2.0.
With FlowLayout mode, you don?t specify precise positionsfor controls. You won?t find any Top or Left properties, nor will you findreferences to X, Y, or Z. Controls are placed relative to other controls. Youcan specify that you want a textbox placed next to a label, or underneath alabel, but the browser will make the final decision on the precise positioningbased on the space available. Tables and Panels are often used to ensure setsof related controls are grouped together. They are often used in complexcombinations, such as nesting a table inside the cell of another table. Commonsets of controls are often converted into user controls so they can be reusedon many pages within a project.
The HTML Table control (found on the HTML tab of theVisual Studio.NET toolbox) is an excellent tool to use for positioning variouselements of a Web page at design time. You resize columns and rows with theclick of a mouse, drag and drop controls wherever you wish, and create newtable cells easily via the right-click menu. If you?d like to be able tointeract with the table at run time, simply mark it with the RunAt = Serverattribute. If you only need to interact with specific rows or cells of thetable at run time, then you can mark only those elements with the RunAt =Server attribute. This can be handy for hiding or highlighting page elementsdynamically.
Don?t confuse the HTML Table control with the Table Webcontrol that?s found in the Web Forms tab of the Visual Studio.NET toolbox. TheTable Web control is a bit weak at design time compared with its HTML controlcounterpart, but it is a powerful tool for building page sections dynamicallyat run time.
It should be noted that if you drop a control onto aGridLayout WebForm and then switch the WebForm to FlowLayout, the control willbe a bit confused about how it should position itself. It will still have theabsolute positioning style elements in its HTML definition, and therefore maynot flow quite as you?d expect. If you truly want the control to switch toFlowLayout, you can go into the HTML view of the page and delete thepositioning style attributes. Alternatively, you can delete the control anddrag a new instance of the control onto the form in its place. This new controlwill clearly see that the form is using FlowLayout and will conform withouthassles.
Why Be Choosey?
Don?t stress out about which pageLayout mode to pick. Youcan have the best of both worlds. On the HTML tab of your Visual Studio.NETtoolbox you?ll find two often-ignored controls named Flow Layout Panel and GridLayout Panel. You can use either of these controls on any WebForm, regardlessof the WebForm?s pageLayout property value. As you might have guessed, thesecontrols will let you have a GridLayout area inside a FlowLayout page, andvice-versa. This can certainly be useful for leveraging the strengths (andnegating the weaknesses) of both techniques. When placing a control inside aGrid 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 GridLayout Panels.
These special panel controls can also be useful whendesigning your own Web controls, because you can use one to specify theplacement of your control?s various elements using whichever layout techniqueyou prefer ? without regard to the pageLayout property of the hosting page.
Conclusion
In summary, although FlowLayout is usually the bestdefault for ASP.NET development, don?t be afraid to switch to GridLayout whenyou need it ? especially if wide compatibility is not a requirement. Theimportant things to understand are the benefits and drawbacks of the availableoptions, and how various techniques can be mixed together to accomplish anydesign imaginable. Hopefully you now have a better understanding of these typesof control positioning details.
Steve C. Orr is anMCSD and a Microsoft MVP in ASP.NET. He?s been developing software solutionsfor leading companies in the Seattlearea for more than a decade. When he?s not busy designing software systems orwriting about them, he can often be found loitering at local user groups andhabitually lurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.netor e-mail him at mailto:Steve@Orr.net.
Position Controls Created at Run Time
Q: How do I positioncontrols that are created at run time?
A: After instantiating the control, add it to the controlcollection of a container control that exists at design time, such as a Panel,TableCell, or PlaceHolder. The PlaceHolder control is often the best choice insuch a situation because this is the main purpose of its existence. APlaceHolder control allows you to define a position for a control (or set ofcontrols) at design time, even though the controls themselves won?t exist untilrun time. Maybe you don?t even know what kind of control will be created, butyou can still define its future placement. Here?s a code snippet to give youthe 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);