In many ASP.NET WebForms applications, developers face a common UI challenge: How to keep a selected button visually active after a postback.

This scenario is especially common when buttons are used to filter data, such as:

Since WebForms relies on server-side postbacks, relying solely on CSS :hover or JavaScript is not sufficient. Once a postback occurs, the UI state is lost unless it is explicitly handled from the backend.

This article explains a backend-driven approach to solve this problem cleanly and reliably.

Problem Statement

<div class="Header">

<h5 class="review mb-0">Review Your Order</h5>

<asp:Button ID="btnShowPending" runat="server" Text="Show Pending" OnClick="btnShowPending_Click" CssClass="btn custom-btn" />

<asp:Button ID="btnShowReplaced" runat="server" Text="Show Replaced" OnClick="btnShowReplaced_Click" CssClass="btn custom-btn" />

<asp:Button ID="btnShowAll" runat="server" Text="Show All" OnClick="btnShowAll_Click" CssClass="btn custom-btn" /> </div>

We have three buttons:

Requirements:

Why Backend Handling Is Required

In ASP.NET WebForms:

Therefore, the backend must decide which button is active and apply the appropriate CSS class during rendering.

CSS for Active Button State

We start by defining a reusable CSS class:

.custom-btn {
    color: #ffffff;
    background-color: #003f88;
    padding: 15px;
    border: none;
    border-radius: 10px;
}

.custom-btn:hover {
    background-color: #002f66;
}

.custom-btn.active {
    background-color: #002f66;
}

The .active class represents the selected button.

Backend Strategy

The backend logic follows three principles:

  1. Reset all buttons to default state

  2. Apply .active class only to the selected button

  3. Store the selected state using ViewState

Centralized Method to Handle Active State

Instead of repeating code in every button click, we create a helper method:

private void SetActiveButton(string activeButton)
{
    btnShowPending.CssClass = "btn custom-btn";
    btnShowReplaced.CssClass = "btn custom-btn";
    btnShowAll.CssClass = "btn custom-btn";

    if (activeButton == "Pending")
        btnShowPending.CssClass += " active";
    else if (activeButton == "Replaced")
        btnShowReplaced.CssClass += " active";
    else if (activeButton == "All")
        btnShowAll.CssClass += " active";

    ViewState["ActiveButton"] = activeButton;
}

This method ensures:

Button Click Events with Backend Control

Each button click:

Example:

protected void btnShowPending_Click(object sender, EventArgs e)
{
    SetActiveButton("Pending");
    rep_data.DataSource = dv;
    rep_data.DataBind();
}

The same pattern is used for Replaced and All buttons.

Default Active Button on Page Load

To set a default active button (for example, “Show All”):

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        SetActiveButton("All");
    }
    else if (ViewState["ActiveButton"] != null)
    {
        SetActiveButton(ViewState["ActiveButton"].ToString());
    }
}

This ensures:

Advantages of This Approach

Conclusion

Handling UI state in ASP.NET WebForms requires a backend-first mindset.
By controlling button styles from the server and persisting the state using ViewState, we can deliver a consistent and professional user experience.

This approach is ideal for: