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:
Show Pending records
Show Replaced records
Show All records
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:
Show Pending
Show Replaced
Show All
Requirements:
Why Backend Handling Is Required
In ASP.NET WebForms:
Every button click triggers a postback
The page is re-rendered
CSS :hover works only during mouse interaction
Client-side active states do not persist automatically
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:
Reset all buttons to default state
Apply .active class only to the selected button
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
Fully backend-driven (no JavaScript dependency)
Works reliably with postbacks
Easy to maintain and extend
Clean separation of UI logic and data logic
Suitable for enterprise WebForms applications
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: