代码之家  ›  专栏  ›  技术社区  ›  Greg B

将数据传递给服务器控件中的子控件的正确模式

  •  2
  • Greg B  · 技术社区  · 15 年前

    我正在与第三方系统合作,以实现网站中的某些表单。

    第三方系统为这些表单提供了XML定义。 例如

    <form>
        <segment>
            <label>The header</label>
            <fields>
                ...
                <field>
                    <id>field_Dob</id>
                    <type>Date</type>
                    <label>Date of Birth</label>
                    <required>1</required>
                </field>
                ...
            </fields>
        </segment>
        ...
    </form>
    

    我正在服务器控件中分析此XML,并通过编程生成控件树。控件的标签在XML中传递。

    这是我们的建议的一部分“注入”小帮助文本到这个表格。

    理想情况下,我希望从顶级控件的标记中传入这些帮助文本,以便非开发人员(HTML Monkies)可以更改帮助文本,并通过其ID将它们与字段关联。类似于

    <controls:MyCrazyForm runat="server">
        <helpTexts>
            <helpText for="field_Dob">
    Some rambling nonsense to do with the DOB field
            </helpText>
            ...
        </helpTexts>
    </controls:MyCrazyForm>
    

    控件是递归解析的。

    表单为每个段创建字段集,字段集根据数据类型创建多个字段xxx(其中xxx=日期、文本、组合框等)。

    FieldXXX类型创建一个DIV,然后创建几个标准的.NET控件(文本框、DropDownList等)来实际呈现自己。此时,在containing DIV中,我需要输出帮助文本。

    我的问题

    将这些文本从顶级表单控件获取到这些子控件的“最佳”方法是什么?这些子控件在控件树中的深度为3或4级。

    页面上永远只有这些表单中的一个。 我应该把最高级的表格做成单件的形式,然后像这样……?

    if(MyCrazyForm.Instance.HelpTexts.ContainsKey("theIdOfTheCurrentField"))
    {
        this.HelpText = MyCrazyForm.Instance.HelpTexts["theIdOfTheCurrentField"];
    }
    

    我应该将对表单的引用一直传递到树的每个控件中吗(这看起来很混乱)?

    我的目标是英里 建筑学 对于这个(尽管它目前工作得很好)形式,我应该看看不同的实现方法吗?

    谢谢

    7 回复  |  直到 15 年前
        1
  •  1
  •   Ozan HELPY    15 年前

    它一开始可能更复杂,但更容易维护,为什么不通过XSL处理器运行XML文件呢?XSLT文件会将helptexts文件的helptext节点分配给相应的字段节点。

     <?xml version="1.0" encoding="ISO-8859-1"?>
    <form>
        <segment>
            <label>The header</label>
            <fields>
                <field>
                    <id>field_name</id>
                    <type>string</type>
                    <label>Name</label>
                    <required>1</required>
                </field>
                <field>
                    <id>field_Dob</id>
                    <type>Date</type>
                    <label>Date of Birth</label>
                    <required>1</required>
                </field>
            </fields>
        </segment>
    </form>
    

    XSLT文件:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!-- Edited by XMLSpy® -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
      <xsl:template match="/form/segment/fields/field[id='field_name']">
        <xsl:copy>
          <xsl:element name="helptext">This is a Name helptext.</xsl:element> 
          <xsl:apply-templates/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="/form/segment/fields/field[id='field_Dob']">
        <xsl:copy>
          <xsl:element name="helptext">This is a Date of birth helptext.</xsl:element> 
          <xsl:apply-templates/>
        </xsl:copy>
      </xsl:template>
    
        <xsl:template match="node() | text()">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>
    

    得出这样的结论:

    <form>
        <segment>
            <label>The header</label>
            <fields>
                <field>
    <helptext>This is a Name helptext.</helptext>
                    <id>field_name</id>
                    <type>string</type>
                    <label>Name</label>
                    <required>1</required>
                </field>
                <field>
    <helptext>This is a Date of birth helptext.</helptext>
                    <id>field_Dob</id>
                    <type>Date</type>
                    <label>Date of Birth</label>
                    <required>1</required>
                </field>
            </fields>
        </segment>
    </form>
    

    现在可以像以前一样分析这个XML文件,但是现在可以在生成表单元素的同时获得帮助文本。您的HTML蒙奇只需要编辑XSLT文件,或者您只需要包含另一个文件:

      <xsl:template match="/form/segment/fields/field[id='field_Dob']">
        <xsl:copy>
          <xsl:element name="helptext">
            <xsl:copy-of select="document('field_Dob.txt')"/> 
          </xsl:element> 
          <xsl:apply-templates/>
        </xsl:copy>
      </xsl:template>
    

    您可以在网上试用XSL here

        2
  •  1
  •   Vinay Sajip    15 年前

    正如这里的其他答案所提出的那样,我认为一种不同的方法可能是有价值的,这取决于您案例的具体情况。与您所描述的类似的问题——将一些特定的文本与表单上的某些控件关联起来——已经为更一般的国际化案例(即资源)解决了。我知道这与其他答案不同,而不是直接问你问题中的问题,但资源似乎很好地满足了需求,如下所述。我不是回答你关于控制之间信息流的具体问题,而是考虑你试图达到的最终结果。如果我误解了什么,就对我宽容一点。

    1. 表单中的每个表单和字段都具有唯一的标识。因此,可以从表单和字段中唯一地构造资源ID。
    2. 资源源文件只是XML,完全独立于UI的细节,可以交给非开发人员以填充相关的帮助文本。如果更改用户界面,则不需要更改此文件 完全 .
    3. 在呈现时,您只需使用表单中的资源ID获取表单中某个域的资源,并根据需要将文本合并到UI中即可。
    4. 由于i18n/l10n使用了相同的方法,所以它有很好的文档记录、很好的理解、声明性、简单和性能。
        3
  •  0
  •   polyglot    15 年前

    向上遍历控件的父级,直到找到特定类型的控件,或者使用名为“helptexts”的特定成员变量,怎么样?

    这是一种动态编程方法,但是对于某些基础设施设计元素,只要这些方法是有限的,并且对为什么采用这种设计方法进行了评论,我会发现它是可以接受的。

    这将使用反射API和通用的静态助手函数,例如

    GetHelpTextFromParent(Control controlParent, string id)
    

    然后,这将检查controlParent以查看它是否包含成员变量helptexts,然后按id查找helptext。否则,它将使用controlParent的父级递归调用getHelpTextFromParent,直到出现合适的终止条件为止。(我提到了“合适的终止条件”,因为在您到达桌面窗口之前保持这个状态可能是次优的,您可能希望在那之前终止递归,但这将是一个测试/调试问题。)

        4
  •  0
  •   user134706    15 年前

    如果你是 在服务器控件中分析此XML并通过编程生成控件树 你如何确保HTML人员保持这些ID的同步?如果他们可以访问这些XML,也许您应该让他们在那里而不是在ASPX上添加帮助文本。

    但为了回答您的问题,我想您是在读取和构建ASPX标记之后分析XML,这样您就可以在分析XML之前索引这些文本。然后,当您实际构建动态控制树时,您将根据源XML中定义的控制的ID查找索引,并在此时将其连接起来。

    编辑:好的,根据您如何构建这些子控件,我将在内部公开表单的所有内联帮助文本,作为由控件ID索引的属性,该属性将提供帮助文本或空字符串。我不确定我知道 mycrazyform.instance 不过。

        5
  •  0
  •   Juozas Kontvainis    15 年前

    我建议创建这样的接口

    interface IHelpTextProvider
    {
        Dictionary<string, string> HelpTexts
        {
            get;
        }
    }
    

    然后,表单控件可以实现此接口,并在创建字段集和fieldxxx控件时传递对此接口的引用。

    或者,您可以按照polyglot建议的方式执行,当需要帮助文本时,fieldxxx控件将递归地遍历其父控件,直到找到实现iHelptextProvider接口的父控件为止。

        6
  •  0
  •   Fredrik Mörk    15 年前

    您可以在服务器控件中创建一个事件,每当需要/需要给定字段的帮助文本时,都会引发该事件。表单可以挂接一个事件处理程序并响应它。这样,您就不需要传递某个对象来授予服务器控件对信息的访问权。为此,我们需要做三件事。

    创建EventArgs类:

    class HelpTextEventArgs : EventArgs
    {
        public string Text { get; set; }
        public string FieldId { get; private set; }
        public HelpTextEventArgs(string fieldId)
        {
            FieldId = fieldId;
        }
    }
    

    在服务器控件中创建事件:

    public event EventHandler<HelpTextEventArgs> HelpTextRequested;
    
    protected void OnHelpTextRequested(HelpTextEventArgs e)
    {
        EventHandler<HelpTextEventArgs> evt = this.HelpTextRequested;
        if (evt != null)
        {
            evt(this, e);
        }
    }
    // wrapper for the event raising method for easier access in the code
    public string GetHelpText(string fieldId)
    {
        HelpTextEventArgs e = new HelpTextEventArgs(fieldId);
        OnHelpTextRequested(e);
        return e.Text;
    }
    

    …并以可以访问帮助文本的形式设置事件处理程序:

    private void Page_Load(object sender, EventArgs e)
    {
        ServerControl.HelpTextRequested += ServerControl_HelpTextRequested;
    }
    
    private void ServerControl_HelpTextRequested(object sender, HelpTextEventArgs e)
    {
        e.Text = FindHelpText(e.FieldId);
    }
    

    使用这种方法,即使宿主表单不提供帮助文本服务,代码也可以正常工作;服务器控件并不取决于是否附加了事件处理程序。

        7
  •  0
  •   shahkalpesh    15 年前

    正如Ozam建议的那样,您可以使用XSL。

    与第三方XML文件结构类似的单独的XML文件(每个XML节点包含helptext)很好&您可能需要合并(?)在某种程度上。

    我不知道这是否有任何帮助。