長時間作業 (檔案上傳、報表產生、複雜運算) 期間,使用者可能重複點擊按鈕,導致重複提交、資料錯誤、伺服器過載。需在用戶端即時給予視覺回饋並禁用按鈕。
[ToolboxData("<{0}:PleaseWaitButton runat=server>{0}:PleaseWaitButton>")]
public class PleaseWaitButton : Button
{
// 等待時顯示的文字
public string PleaseWaitText
{
get => ViewState["PleaseWaitText"] as string ?? "";
set => ViewState["PleaseWaitText"] = value;
}
// 等待時顯示的圖片 (GIF 動畫)
public string PleaseWaitImage
{
get => ViewState["PleaseWaitImage"] as string ?? "";
set => ViewState["PleaseWaitImage"] = value;
}
// 顯示模式
public enum PleaseWaitTypeEnum { TextOnly, ImageOnly, TextThenImage, ImageThenText }
public PleaseWaitTypeEnum PleaseWaitType
{
get => (PleaseWaitTypeEnum)(ViewState["PleaseWaitType"] ?? PleaseWaitTypeEnum.TextOnly);
set => ViewState["PleaseWaitType"] = value;
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
// 註冊客戶端腳本
string script = @"
function PleaseWait(btn, text, img, type) {
var div = document.createElement('DIV');
div.style.position = 'absolute';
div.style.left = '0px'; div.style.top = '0px';
div.style.width = btn.offsetWidth + 'px';
div.style.height = btn.offsetHeight + 'px';
div.style.backgroundColor = '#FFFFCC';
div.style.border = '1px solid #FFCC00';
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.justifyContent = 'center';
div.style.zIndex = 1000;
div.style.fontSize = '12px';
div.style.color = '#CC0000';
div.style.whiteSpace = 'nowrap';
var html = '';
if (type == 0 || type == 2) html += text; // TextOnly, TextThenImage
if (type == 1 || type == 2 || type == 3) { // ImageOnly, TextThenImage, ImageThenText
if (img) html += (html ? ' ' : '') + '
';
else html += (html ? ' ' : '') + 'Loading...';
}
div.innerHTML = html;
btn.style.display = 'none';
btn.parentNode.insertBefore(div, btn);
btn._pleaseWaitDiv = div;
}";
ScriptManager.RegisterStartupScript(this, GetType(), "PleaseWaitFunc", script, true);
// 綁定 onclick
string waitHtml = BuildWaitHtml();
string onclick = $"PleaseWait(this, '{EscapeJs(PleaseWaitText)}', '{EscapeJs(PleaseWaitImage)}', {(int)PleaseWaitType}); ";
if (!string.IsNullOrEmpty(OnClientClick))
onclick = OnClientClick + "; " + onclick;
OnClientClick = onclick + "__doPostBack('" + ClientID + "',''); return false;";
}
string BuildWaitHtml()
{
// 由 JavaScript 動態建立,這裡僅準備參數
return "";
}
string EscapeJs(string s) => s.Replace("\\", "\\\\").Replace("'", "\\'").Replace("\n", "\\n").Replace("\r", "\\r");
protected override void Render(HtmlTextWriter writer)
{
// 使用 DIV 包裹,避免 display:none 影響回發
writer.WriteBeginTag("div");
writer.WriteAttribute("id", ClientID + "_wrapper");
writer.Write(HtmlTextWriter.TagRightChar);
base.Render(writer);
writer.WriteEndTag("div");
}
}
<%@ Register TagPrefix="cc" Namespace="MyControls" Assembly="MyControls" %>
匯入完成!共處理 1234 筆資料。
protected void btnUpload_Click(object sender, EventArgs e)
{
// 模擬耗時作業
System.Threading.Thread.Sleep(5000); // 實際為檔案處理、資料庫操作等
// 完成後隱藏按鈕、顯示成功訊息
btnUpload.Visible = false;
pnlSuccess.Visible = true;
}