2012年2月5日 星期日

ASP.NET 使用MasterPage跨網頁傳遞參數問題

一般跨網頁傳遞參數,很簡單到很多書都不講,大致有五種方法。
以送出頁為SendToB.aspx,接收頁為RecvFromA.aspx為例。

1.透過Http Html Form Get:
    送出頁:Response.Redirect("~/RecvFromA.aspx?id=" + TextBox1.Text);
    接收頁:string sId = Request.QueryString["id"];
    ◎通用性最佳,但不宜傳送可能有資訊安全疑慮之參數,且要注意參數編碼與轉碼問題。

2.透過Http Html Form Post:
    送出頁:Response.Redirect("~/RecvFromA.aspx"); 或使用 Button的PostBackUrl屬性填入~/RecvFromA.aspx。
    接收頁:string sId = Request.Form["id"];
    ◎通用性次佳,但在Master Page下無效。

3.透過ASP.NET PreviousPage:
    送出頁:Response.Redirect("~/RecvFromA.aspx"); 或使用 Button的PostBackUrl屬性填入~/RecvFromA.aspx。
    接收頁: TextBox oTB = (TextBox)this.PreviousPage.FindControl("TextBox1");
                     this.Label1.Text = oTB.Text;
    ◎只能用於本身且是ASP.NET網站。在Master Page下需要修改程式碼。

4.透過ASP.NET PreviousPage加自訂公用屬性:
    送出頁:先在Class內加上自訂公用屬性。
                  public String SearchString
                  {
                       get
                      {
                           return  TextBox1.Text;
                      }
                   }
                    再使用 Button的PostBackUrl屬性填入~/RecvFromA.aspx 。
    接收頁:將RecvFromA.aspx頁面的第一列後插入以下指令列,<%@ PreviousPageType VirtualPath="~/SendToB.aspx" %>
                    接著在RecvFromA.cs的Page_Load()函式中使用Label1.Text = PreviousPage.SearchString; 取得前頁公用屬性。
    ◎ 只能用於本身且是ASP.NET網站 ,且送出頁與接收頁無法二對一傳遞。不論一般跨網頁或Master Page下都不需要修改程式碼。

5.透過ASP.NET Session傳遞
    送出頁:使用 Button的onClick事件填入Session["SearchString"] = TextBox1.Text;
                    Response.Redirect("~/RecvFromA.aspx");
    接收頁:Page_Load()函式中使用Label1.Text =  Session["SearchString"].ToString();
    ◎ 只能用於本身且是ASP.NET網站,簡單好用跟寫 AP 觀念一樣。

但是,若使用MasterPage跨網頁傳遞參數,第一種方法可以,第二種方法會抓不到,第三種方法則接收頁需要修改語法如下,第四種方法可以,第五種方法可以。

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.PreviousPage != null)
        {
            if (PreviousPage.IsCrossPagePostBack)
            {
                //使用MasterPage時, 使用此語法來查找到前一頁中Content Page內的控制項
                TextBox oTB = (TextBox)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("TextBox1");
             
                //使用MasterPage時, 使用此語法來查找到前一頁中Master Page內的控制項
                //TextBox oTB = (TextBox)this.PreviousPage.Master.FindControl("TextBox1");
             
                //顯示上頁欄位中傳遞過來的參數
                this.Label1.Text = oTB.Text;
            }
        }
    }

---
Welly

2012年2月4日 星期六

淺析 ASP.NET Form Submit Keypress 事件 by Enter key

老一輩程式設計師都知道,以前在DOS下寫資料庫 AP,在畫面下按Enter鍵跳下一個欄位是預設再平常不過的事,但到了Windows AP下這功能是要自己在 Form.OnKeyPress事件寫處理指令,可是,到了ASP.NET WEB AP下這功能卻又成了預設功能,挺有趣。

ASP.NET Form Submit Keypress 事件 by Enter key其實說到底並不是ASP.NET 的程式設計問題,卻是關於Html Form 中的Submit 按鈕如何運作問題。


ASP.NET Form Submit Keypress 事件 by Enter key測試一:
當你的游標焦點進入某個表單控制項的時候,會啟動該表單中第一個(依Form 上控制項佈局,從左到右,從上至下算起) type="submit" 的按鈕(假如有),等待回應鍵盤及滑鼠的 Keypress 事件,以Submit該Form。
你可以測試一下以下程式碼:
   1. ﹤form action=""﹥
   2. ﹤input type="text" /﹥
   3. ﹤input type="submit" value="submit" /﹥
   4. ﹤/form﹥
   5. ﹤form action=""﹥
   6. ﹤input type="text" /﹥
   7. ﹤input type="button" value="submit" /﹥
   8. ﹤/form﹥


ASP.NET Form Submit Keypress 事件 by Enter key測試二:
在 ASP.NET 2.0 中的 Button 控制項,預設轉換成 Html 為 ﹤input type="submit"﹥,此時不一定要在 Form 的屬性宣告 submit 事件,因為,submit 型態按鈕就是用來提交Form ,在 ASP.NET 1.x時是轉換成 ﹤input type="button" onclick="_doPostBack(...)" /﹥,此普通 button 就不具備 submit 的上述預設提交行為。


ASP.NET Form Submit Keypress 事件 by Enter key測試三:
依上述,若想要禁用此項預設行為有二種方法。

(1)設置 Form 控制項的 DefualtButton 為你希望回應 Enter 的真正按鈕:
   1. ﹤form id="form1"
   2.
   3. runat="server"
   4.
   5. defaultbutton="Button1"﹥

◎注意 DefaultButton = ﹤ ﹤TargetButton.ID﹥﹥,因此這對複合控制項中,比如Login樣版的 Button 可能無效。
◎也可用程式動態指定 this.Form.DefaultButton = "ContentPlaceHolder1$btsubmit";
值得注意的是,如果用了Master Page,那麼要在按鈕ID前加上 Master 的ID:ContentPlaceHolderID和一個金錢符號($)。
◎例如:
‧在Master Page內用:
   1. protected void Page_Load(object sender, EventArgs e)
   2. {
   3.   this.Form.DefaultButton = "ctl00$ContentPlaceHolder1$Login2$LoginButton";
   4. }
‧在Content Page內用:
   1. protected void Page_Load(object sender, EventArgs e)
   2. {
   3.   this.Page.Form.DefaultButton = "ctl00$ContentPlaceHolder1$Login2$LoginButton";
   4. }
‧在一般(未使用Master Page)情況頁面內:
   1. protected void Page_Load(object sender, EventArgs e)
   2. {
   3.   this.Form.DefaultButton = "LoginButton ";
   4. }
‧在使用者自定控制項(.ascx)內:
   1.請先在引用該控制項的表單外部加一個 Panel 包住,
     <asp:Panel ID="Panel1" runat="server">
        .....//使用者自定控制項的內容
     </asp:Panel>
   2.然後再指定 Panel1.DefaultButton = "btsubmit";


(2)修改 Button 呈現方式 UseSubmitBehavior="false":
   1. ﹤asp:Button ID="Button1"
   2.
   3. runat="server" Text="Button"
   4.
   5. onclick="Button1_Click"
   6.
   7. UseSubmitBehavior="false" /﹥

◎個人建議採用(2)作法,簡單易記,效果明確。


另外,可以使用控制焦點的方式,過濾(擋掉) Enter 鍵按下的處理,做法是:
(1)記錄下需要設定過濾的焦點控制項ID,若不知可用獲取當前頁面焦點所在控制項的ID方法:
document.ActiveElement

(2)以ASP.NET Form上在TextBox1中輸入內容後,按下Enter鍵後,就執行Button1的click方法範例下,我們可在Page_Load事件方法中動態指定 TextBox1的屬性,依下寫入:
   1. TextBox1.Attributes.Add("onkeydown",
   2.
   3. "if(event.which || event.keyCode){
   4.
   5. if ((event.which == 13) || (event.keyCode == 13)) {
   6.
   7. document.getElementById('"+
   8.
   9. Button1.UniqueID+"').click();return false;}}
   10.
   11. else {return true}; ");

◎以上作法其實是針對 TextBox1的onKeydown 事件(或改成 Keypress 事件亦可)內,若按下的是 Enter 鍵時不執行下去,但若按下的是滑鼠左鍵,則執行下去。只能針對特定 TextBox 指定,萬一 Form 上有10個 TextBox 則要用 foreach 逐個指定。


參考資料來源:
1.浅析ASP.NET回车提交事件(转)
http://www.cnblogs.com/jiajiayuan/archive/2011/08/26/2154596.html

2. HtmlForm.DefaultButton 屬性
http://msdn.microsoft.com/zh-tw/library/system.web.ui.htmlcontrols.htmlform.defaultbutton(v=vs.80).aspx

3.Master page button event Overloading by content page button event when enter key is pressed
http://stackoverflow.com/questions/4303009/master-page-button-event-overloading-by-content-page-button-event-when-enter-key

4.ASP.NET 2.0 - Enter Key - Default Submit Button
http://geekswithblogs.net/ranganh/archive/2006/04/12/74951.aspx

5.如何讓使用MasterPage啟用 DefaultButton 屬性
http://www.wretch.cc/blog/bigdstut/14296848

6.Setting the default Button for a TextBox in ASP.NET
http://weblogs.asp.net/rajbk/archive/2003/12/11/setting-the-default-button-for-a-textbox-in-asp-net.aspx


---
Welly Lin