• FineUI小技巧(5)向子窗口传值,向父窗口传值


    前言

    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小技巧》系列文章目录

     

  • 相关阅读:
    shell test条件检查
    Mysql 创建只读账户
    cmd 批处理创建 IIS 站点
    Linux date获取时间戳
    数据结构与算法面试题80道(25)
    数据结构与算法面试题80道(24)
    数据结构与算法面试题80道(23)
    数据结构与算法面试题80道(22)
    数据结构与算法面试题80道(21)
    数据结构与算法面试题80道(20)
  • 原文地址:https://www.cnblogs.com/sanshi/p/3802467.html
Copyright © 2020-2023  润新知