Steve Wellens

Programming in the .Net environment

Sponsors

Links

December 2008 - Posts

GUI 101 - Group Boxes

Often, it's the little things that matter. In any application, small changes to the user interface can have a major impact on the readability and usability of a form. Fonts, element spacing, order of elements, colors, etc., all come into play. A skillful designer can make a few tweaks to a crappy interface and make it a delight to use. It's easy to be seduced by the siren songs of AJAX, Silverlight, gradient backgrounds, etc., but simply grouping controls logically can be much more effective in providing a good user experience and…it won't make your web application run like a sick dog.

If you have moved from regular Windows programming to Web programming, you might be missing one of the simplest, yet most powerful, constructs in the graphical interface: Group Boxes. The majority of Windows Form applications use Group Boxes yet you almost never see them on a web page. In HTML, they are called FieldSets. There is not a corresponding Server Control and FieldSets are not on the HTML tab of the Visual Studio tool box. Perhaps that is why we don't often see them.

Here is a FieldSet using CSS to control the appearance:

    .GroupBox
    {
        border: 1px solid #0000FF;
        display: inline;
        padding: 8px;
    }
    .GroupBoxLegend
    {
        padding-bottom: 4px;
    }
 
    <fieldset class="GroupBox">
        <legend class="GroupBoxLegend">Shipping</legend>
        <asp:RadioButtonList ID="RadioButtonListShipping" runat="server">
            <asp:ListItem Text="US Mail"></asp:ListItem>
            <asp:ListItem Text="Fed Ex"></asp:ListItem>
            <asp:ListItem Text="UPS"></asp:ListItem>
            <asp:ListItem Text="Pony Express"></asp:ListItem>
        </asp:RadioButtonList>
    </fieldset>

Here is the result:

It looks fine, but you don't have to use FieldSets.

It's a carefully hidden fact but the Panel Control can be used to create FieldSets. Normally, when you use a Panel Control, a simple div is rendered. But, when you add GroupingText to the Panel Control, a FieldSet is rendered inside the div. In addition, attributes are magically added to the borders of the FieldSet to give it the appearance of a typical windows group box. Style is not listed as an attribute of a Panel control, but you can add it to control the panel's position.

    <asp:Panel ID="PanelSize" runat="server" GroupingText="Size"       
        style="width:116px; top: 341px; left: 10px; position: absolute; height: 128px;" >
        <asp:RadioButtonList ID="RadioButtonSize" runat="server">
            <asp:ListItem Text="Small"></asp:ListItem>
            <asp:ListItem Text="Medium"></asp:ListItem>
            <asp:ListItem Text="Large"></asp:ListItem>
            <asp:ListItem Text="Ex Large"></asp:ListItem>
        </asp:RadioButtonList>
    </asp:Panel>

Here is the result (note the styled border):

If you are interested, as I certainly was, in comparing the rendered HTML of a panel with and without grouping text, you can quickly dummy up a function like this:

    protected void Button1_Click(object sender, EventArgs e)
    {
        if (PanelSize.GroupingText == "")
            PanelSize.GroupingText = "Size";
        else
            PanelSize.GroupingText = "";
    }

As usual, once you start tweaking GUIs, you can spend hours of precious time getting it right. With CSS you have much more control over the appearance of details than you do with Windows Forms group boxes. You can change just about everything which may, or may not, be a good thing depending on your schedule.

I hope you found this useful.

Steve Wellens

PS: Thanks to the anonymous poster Ben, who gracefully pointed out a critical error in my original post and made this post much more interesting.

Stupid Chart Tricks

The new free Chart Control from Microsoft is awesome (for download details see my original post here).  But if you can avoid being dazzled by the plethora of charting features, you may realize it can be used for other tasks.

You can use the Chart Control to display simple text dynamically in a bitmap.

You don't need to do any plotting to use the control.

  1. Drop a Chart onto a page.
  2. Delete all the sub-elements inside the Chart Element:

  3.     <asp:Chart ID="Chart1" runat="server">
        </asp:Chart>
         
  4. In the properties windows, add and configure the Titles you wish to display. Make sure to give each title a descriptive name so you can access it from code-behind.

Here is what the demo markup looks like:

    <asp:Chart ID="ChartTextOnly" runat="server" 
        BackColor="Transparent" 
        Height="80px"
        Width="612px" 
        EnableViewState="True">
        <Titles>
            <asp:Title BackColor="ForestGreen" 
                BackGradientStyle="LeftRight" 
                BackSecondaryColor="Blue"
                Font="Forte, 16pt" 
                ForeColor="Yellow" 
                Name="MainTitle" 
                Text="Congratulations, you have logged in successfully!"
                BorderColor="Black" 
                ShadowOffset="5">
            </asp:Title>
            <asp:Title Name="Spacer" 
                BackColor="Transparent"
                Font="Courier New, 4pt" 
                Text=" ">
            </asp:Title>
            <asp:Title Alignment="MiddleLeft" 
                BackColor="Transparent" 
                Font="Lucida Calligraphy, 10pt"
                Name="Date" 
                Text="Star Date" 
                TextStyle="Frame">
            </asp:Title>
        </Titles>
    </asp:Chart>

Here is what the code-behind, that dynamically updates the text, looks like:

    public partial class _Default : System.Web.UI.Page
    {
        string UserName = "Matilda";
 
        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack == false// first time only
            {
                ChartTextOnly.Titles["MainTitle"].Text =
                    String.Format("Congratulations {0}, you've logged in successfully!", 
                    UserName);
 
                ChartTextOnly.Titles["Date"].Text = "On Star Date: " + 
                    DateTime.Now.ToLongDateString();
            }
        }

 

And here is what the final product looks like (pretty sexy, eh?):

I know what the smart people are thinking: "Now hold on there Sparky, sure it looks cool, but if the server has to render a new graphic on every page post-back, my users are going to have me tied to a post, stripped to the waist and horse-whipped."

That's true. And I would be the first in line. So, to avoid rendering the image on every post-back, set the ViewState of the chart to true.

Notes:

This is useful if you need to display text that you don't want people to copy and paste. It's like a poor man's Captcha .

Any font can be used. Since the text is rendered at the server, it will be exact and not dependent upon the client machine's fonts.

I thought the space between the two titles was insufficient so I created a third title between them to be a spacer. The height of the space is controlled by the font size of the empty string.

I hope you find this useful.

Steve Wellens

Installing XP SP3 "Access Denied"

I like helping people but I do not like doing support. It's not really my thing. However, when I get a call from my father… I provide support.

He wasn't able to install Service Pack 3 on his Windows XP computer. I tried it and, after a very lengthy process, received this message: "Access Denied"

I found a link on a Microsoft Web Site which described the error and offered some workarounds to try:

http://support.microsoft.com/kb/949377

I followed the suggestions but resetting the registry keys did not work (you download and install a tool and then run a command script). The command script tripped up and reported errors on some keys. The keys it gave errors on were deep in the registry: In registry places so deep, dark and remote that even brave men tremble at the mere thought of accessing them. Back to Google…

I found another web site that said the Microsoft provided command script to reset the registry keys was incorrect. They posted this script:

cd /d “%ProgramFiles%\Windows Resource Kits\Tools”
subinacl /subkeyreg HKEY_CURRENT_USER /grant=administrators=f /grant=system=f
subinacl /subkeyreg HKEY_CLASSES_ROOT /grant=administrators=f /grant=system=f
subinacl /subdirectories %SystemDrive% /grant=administrators=f /grant=system=f
subinacl /subdirectories %windir%\*.* /grant=administrators=f /grant=system=f
secedit /configure /cfg %windir%\repair\secsetup.inf /db secsetup.sdb /verbose

This script worked and I was able to install XP SP3 on my father's PC. His virus software had expired so I removed it and installed a free one: Avast.  After the install, I had it do a full system scan. It found a few suspect files which I had the anti-virus software delete.  It was a happy ending.

I hope someone finds this helpful.

Steve Wellens

Posted: Dec 06 2008, 11:27 AM by SGWellens | with no comments
Filed under:
Custom Annotate Your Charts

A few posts back, I described the new Microsoft Chart Controls for the .Net Framework: Chart Demo.   While playing with the controls a bit over the holidays, I was pleasantly surprised to find you can hook into the paint events while the chart is being rendered.

In the code below, I've hooked into the Post Paint event of the chart in the previous demo to add a custom annotation to the chart. Here is what the chart looks like with the date printed and copyright annotation at the bottom:

Custom Annotated Chart

In order to make this happen, you hook into the chart control's PostPaint event:

    <asp:Chart ID="Chart1" runat="server" 
        OnPostPaint="Chart1_PostPaint"    

In the event handler, you are given access to the Graphics object and can draw on the surface of the graph:  

protected void Chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
    if (e.ChartElement is Chart)
    {
        // create text to draw
        String TextToDraw;
        TextToDraw = "Printed: " + DateTime.Now.ToString("MMM d, yyyy @ h:mm tt");
        TextToDraw += " -- Copyright © Steve Wellens";
 
        // get graphics tools
        Graphics g = e.ChartGraphics.Graphics;
        Font DrawFont = System.Drawing.SystemFonts.CaptionFont;
        Brush DrawBrush = Brushes.Black;
 
        // see how big the text will be
        int TxtWidth = (int)g.MeasureString(TextToDraw, DrawFont).Width;
        int TxtHeight = (int)g.MeasureString(TextToDraw, DrawFont).Height;
 
        // where to draw
        int x = 5;  // a few pixels from the left border
 
        int y = (int)e.Chart.Height.Value;
        y = y - TxtHeight - 5; // a few pixels off the bottom
 
        // draw the string        
        g.DrawString(TextToDraw, DrawFont, DrawBrush, x, y);
    }
}

Notes:

In the real world, I would put this in a separate function to be reusable (to keep the demo simple, I left it in the handler).

Several paint events are generated while painting the graph. The text is only drawn when the main chart element is drawn.

To keep the text legible I left an arbitrary 5 pixels between the left side and bottom.

Question:

The chart control has PrePaint events and PostPaint events. I couldn't find any behavioral differences or documentation on the differences. Does anyone know why there are both PrePaint and PostPaint events?

I hope you find this useful.

Steve Wellens

More Posts