HiveBrain v1.2.0
Get Started
← Back to all entries
patternhtmlMinor

Displaying a row of buttons

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
buttonsrowdisplaying

Problem

What the code does is displays a row of buttons and when you click on a button it changes the session so you can see if it's active or not.

Also, this is a link to what the side panel looks like when you click the "programming" button.

There must be a better way to display this code. Does anyone have any ideas?


    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

    '/>

Solution

This can be shortened up quite a bit. First, you have presentation logic intertwined in your ASP code, which is the main cause for the code repetition. Shortening this code and DRY-ing it up involves two main pieces:

  • create a user control to encompass this menu, and only this menu



  • Move all presentation logic into the C# code-behind file



Creating the User Control

First, create a brand new user control and name it something like "MenuUserControl"


    
        
            
        
        
            
        

        


Notice that the CssClass and the button Text is not in the Design file. Moving this into C# not only makes the Design code cleaner, but the resulting C# could will still look pretty clean, and it allows you to leverage Visual Studio's refactoring tools in the future should anything change.

The Code-Behind file:

public partial class MenuUserControl : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
            SetButtonText();
    }

    private void SetButtonText()
    {
        programming1.Text = (string)Session["programmingButtonValue"];
        management1.Text = (string)Session["managementButtonValue"];
        // continue setting button text...
    }

    public void SetActiveButton(string activeButtonId)
    {
        SetButtonState(programming1, activeButtonId);
        SetButtonState(management1, activeButtonId);
        // continue setting button state..
    }

    private void SetButtonState(Button button, string activeButtonId)
    {
        button.CssClass = button.ID == activeButtonId
            ? "mainMenuPanelButtonSelected boxShadowClass"
            : "mainMenuPanelButton boxShadowClass";
    }
}


During the initial GET request to your web application, set the button text using the Session, as described in the SetButtonText private method.

Next, the SetActiveButton method is exposed publically so a parent user control can give the menu control the name of the active button. The logic of "setting the active button" is encapsulated in the SetButtonState class, which recieves a Button object and the active button Id as arguments. The SetActiveButton method just becomes of bunch of calls to SetButtonState, one for each button in the menu.

Using the MenuUserControl

In some parent control, most likely Site.master, add a reference to the MenuUserControl in the Design file:



Then add the menu user control itself:


    
        


Lastly, in the Code-Behind for Site.master call the SetActiveButton method on the menu user control:

public partial class SiteMaster : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        MainMenu.SetActiveButton((string)Session["whichTopMenu"]);
    }
}


Conclusion

This approach has several benefits:

  • The code is more DRY (Don't Repeat Yourself)



  • All presentation logic is in C#, where it belongs



  • By creating a user control just to encapsulate this menu, you've created something that you can reuse if necessary



  • The logic for setting button text and the "active" state lies in C#, allowing you to leverage Intellisense in Visual Studio. Code errors are easier to catch, plus you can use the refactoring tools easier in Visual Studio should anything change in the future.



An Alternative: Using `

You might also try using the
` control instead of a table in the MenuUserControl. You can build your menu items dynamically in C#, but I leave that as a research topic for you.

Code Snippets

<table>
    <tr>
        <td class="mainMenuPanelTD">
            <asp:Button id='programming1' runat='server'
                onclientclick="doFade()"
                onclick='topMenuClick' type='button'/>
        </td>
        <td class="mainMenuPanelTD">
            <asp:Button id='management1' runat='server'
                onclientclick="doFade()"
                onclick='topMenuClick' type='button'/>
        </td>

        <!-- more menu items ... -->
public partial class MenuUserControl : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
            SetButtonText();
    }

    private void SetButtonText()
    {
        programming1.Text = (string)Session["programmingButtonValue"];
        management1.Text = (string)Session["managementButtonValue"];
        // continue setting button text...
    }

    public void SetActiveButton(string activeButtonId)
    {
        SetButtonState(programming1, activeButtonId);
        SetButtonState(management1, activeButtonId);
        // continue setting button state..
    }

    private void SetButtonState(Button button, string activeButtonId)
    {
        button.CssClass = button.ID == activeButtonId
            ? "mainMenuPanelButtonSelected boxShadowClass"
            : "mainMenuPanelButton boxShadowClass";
    }
}
<%@ Register Src="~/UserControls/MenuUserControl.ascx"
    tagname="ButtonList" tagprefix="Menu" %>
<body>
    <div id="page">
        <Menu:ButtonList ID="MainMenu" runat="server" />
public partial class SiteMaster : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        MainMenu.SetActiveButton((string)Session["whichTopMenu"]);
    }
}

Context

StackExchange Code Review Q#67299, answer score: 7

Revisions (0)

No revisions yet.