文章出處

前言

FineUI中經常會用到啟用IFrame的Window控件,這樣有助于從物理上進行代碼解耦和。IFrame的引入就會涉及傳值問題,如何在父窗口和子窗口之間相互傳值呢?

向子窗口傳值

向子窗口傳值只需要把要傳遞的參數放在頁面URL中即可,一般有兩種做法:

  1. 頁面回發,在后臺通過C#代碼拼接需要的URL(推薦做法,方便!)
  2. 頁面第一次加載時,即注冊需要的URL(如果參數是頁面上某輸入框的值,則需要在URL中嵌入JavaScript代碼)

來看一個例子,分別用上述兩種方式實現:

  1. 頁面的初始顯示
  2. 點擊"從列表中選擇"按鈕,彈出選擇窗體(內嵌IFrame頁面),默認選中父頁面文本輸入框中的值
  3. 在彈出框內,點擊"河南",立即關閉彈出框,并把選擇的值放到父頁面的文本輸入框內

 暫時,我們只關心前兩步操作,也即是如何把文本輸入框的值傳遞到子窗口中。

  1. 頁面回發,在后臺通過C#代碼拼接需要的URL(推薦做法,方便!)
    1 <f:TextBox Label="你所在的省份" ID="tbxProvince" Text="安徽" runat="server">
    2 </f:TextBox>
    3 <f:Button ID="Button1" OnClick="Button1_Click" runat="server" Text="從列表中選擇">
    4 </f:Button>
    1 protected void Button1_Click(object sender, EventArgs e)
    2 {
    3     string openUrl = String.Format("./passvalue_iframe_iframe.aspx?selected={0}", HttpUtility.UrlEncode(tbxProvince.Text));
    4 
    5     PageContext.RegisterStartupScript(Window1.GetShowReference(openUrl));
    6 }

    在按鈕的回發事件中,我們很容易通過控件的服務器端屬性(tbxProvince.Text)來拼接需要的URL

  2. 頁面第一次加載時,即注冊需要的URL(如果參數是頁面上某輸入框的值,則需要在URL中嵌入JavaScript代碼)
    1 <f:TextBox Label="你所在的省份" ID="tbxProvince" Text="安徽" runat="server">
    2 </f:TextBox>
    3 <f:Button ID="Button1" EnablePostBack="false" runat="server" Text="從列表中選擇">
    4 </f:Button>
    1 protected void Page_Load(object sender, EventArgs e)
    2 {
    3     if (!IsPostBack)
    4     {
    5         string openUrl = String.Format("./passvalue_iframe_iframe.aspx?selected=<script>encodeURIComponent({0})</script>", tbxProvince.GetValueReference());
    6  
    7         Button1.OnClientClick = Window1.GetShowReference(openUrl);
    8     }
    9 }

    注意:在上述 openUrl 參數中,我們嵌入了 <script> 標簽,這個是 FineUI 支持的特殊用法(在其他系統中可能不支持這個用法)!

    大家一定要明白一個事情:在頁面第一次加載時,我們不可能直接獲得文本輸入框的值來拼接URL,因為用戶以后可能會修改這個值!

    如果你這時查看頁面源代碼,上述對 openUrl 操作被轉換為腳本:

    1 F('Window1').f_show('/iframe/passvalue_iframe_iframe.aspx?selected=' + encodeURIComponent(F('SimpleForm1_tbxProvince').getValue()));

     

向父窗口傳值(FineUI內置方法)

向父窗口傳值就沒那么直觀了,幸好FineUI內置了一對方法來簡化這個操作,應該可以滿足 80% 的業務需求:

  1. 打開子窗口時,調用 GetSaveStateReference,告知FineUI將來的返回值要保存到哪些控件
    1 protected void Button1_Click(object sender, EventArgs e)
    2 {
    3     string openUrl = String.Format("./passvalue_iframe_iframe.aspx?selected={0}", HttpUtility.UrlEncode(tbxProvince.Text));
    4 
    5     PageContext.RegisterStartupScript(Window1.GetSaveStateReference(tbxProvince.ClientID)
    6             + Window1.GetShowReference(openUrl));
    7 }

     

  2. 關閉子窗口時,調用 GetWriteBackValueReference,將返回值保存到父窗口的這些控件
    1 protected void ddlSheng_SelectedIndexChanged(object sender, EventArgs e)
    2         {
    3             if (ddlSheng.SelectedValue != "-1")
    4             {
    5                 PageContext.RegisterStartupScript(ActiveWindow.GetWriteBackValueReference(ddlSheng.SelectedValue) + ActiveWindow.GetHideReference());
    6             }
    7         }

     

如果希望同時傳遞多個值,GetSaveStateReference 和 GetWriteBackValueReference 分別提供了重載方法。

向父窗口傳值(窗體的關閉事件)

上一節我們講到FineUI關閉窗體的三種處理方式,分別是隱藏、隱藏回發和隱藏刷新,其中隱藏回發可以指定回發參數,正好用來向父頁面傳遞參數。

  1. 在子窗體中注冊窗體關閉腳本,把要傳遞的參數放置在 GetHidePostBackReference 中
    1 PageContext.RegisterStartupScript(ActiveWindow.GetHidePostBackReference("SelectProvince$要傳遞的參數"));

     

  2. 在父頁面的Window關閉事件中
    1 protected void Window1_Close(object sender, WindowCloseEventArgs e)
    2 {
    3     if (e.CloseArgument.StartsWith("SelectProvince$"))
    4     {
    5         string provinceName = e.CloseArgument.Substring("SelectProvince$".Length);
    6 
    7         ddlSheng.SelectedValue = provinceName;
    8     }
    9 }

    其中,"SelectProvince$"是為了區分不同情況觸發的窗體關閉事件。

    通過這種方式,無需編寫 JavaScript 代碼也能方便的實現子窗體到父窗體的參數傳遞。

 

向父窗口傳值(自定義腳本)

這種方法需要自己編寫JavaScript,需要對FineUI的客戶端腳本比較熟悉,但也更加靈活。下面通過一個示例講解:

  1. 頁面的初始顯示

    在父頁面定義全局 JavaScript 函數:
    1 <script>
    2     var shengClientID = '<%= ddlSheng.ClientID %>';
    3 
    4     function selectProvince(name) {
    5         F(shengClientID).setValue(name);
    6     }
    7 </script>

    如果子窗體可以找到本頁面的JavaScript對象window,則可以方便的調用 window.selectProvince 來傳遞參數

  2. 點擊"從列表中選擇",在Top頁面打開窗體,在彈出窗體內選擇省份

    1 <map id="ChinaMap" name="ChinaMap">
    2             <area href="javascript:select('黑龍江');" coords="398,52,442,72" shape="rect">
    3             <area href="javascript:select('吉林');" coords="400,96,433,111" shape="rect">
    4 </map>
    1 <script>
    2     function select(provinceName) {
    3         // 返回當前活動Window對象(瀏覽器窗口對象通過F.wnd.getActiveWindow().window獲取)
    4         var activeWindow = F.wnd.getActiveWindow();
    5         activeWindow.window.selectProvince(provinceName);
    6         activeWindow.f_hide();
    7     }
    8 </script>

    上面的 F.wnd.getActiveWindow 返回的是當前活動的Window控件實例,F.wnd.getActiveWindow().window就是Window控件實例所在的頁面的JavaScript對象window。知道了這個關系,就很容易理解這段代碼了。

     

一個小問題,為什么不直接調用 parent.selectProvince ?

能夠提出這個問題的一般 JavaScript 功底還不錯!

不過這個地方還真不行,如果你注意到前面的一個細節“點擊從列表中選擇,在Top頁面打開窗體”,所以現在的層次結構是這樣的:

  1. 在表單頁面定義了 window.selectProvince
  2. Window控件實例(編輯框)在主框架頁面(也就是表單頁面的父頁面)
  3. 中國地圖所在頁面的 parent 是主框架頁面,非表單頁面!

 

本章小結

本篇文章介紹了從父窗體向子窗體傳值,可以通過子窗體頁面的URL地址,而拼接此URL地址又有兩種做法,我們推薦在后臺通過C#方式做,簡單方便!從子窗體向父窗體傳值也有多種做法,FineUI提供的一對函數(GetSaveStateReference 和 GetWriteBackValueReference )足以滿足大部分的需求,其次還可以通過窗體的關閉事件以及自定義JavaScript腳本來完成傳值。

源代碼與在線示例

本系列所有文章的源代碼均可自行下載:http://fineui.codeplex.com/

在線示例:

  1. http://fineui.com/demo/#/demo/iframe/passvalue_iframe.aspx
  2. http://fineui.com/demo/#/demo/iframe/triggerbox_iframe.aspx
  3. http://fineui.com/demo/#/demo/iframe/selectprovince1.aspx

 

如果本文對你有所啟發或者幫助,請猛擊“好文要頂”,支持原創,支持三石!

 

另附24張專業版高清大圖

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

《FineUI小技巧》系列文章目錄

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()