【问题标题】:Databinding in inner .ascx control and FormView内部 .ascx 控件和 FormView 中的数据绑定
【发布时间】:2011-01-31 17:49:36
【问题描述】:

我在 FormView 中有 ascx 控件。我想要的是在 ascx 中使用语法 Bind。 这是我的页面:

    <asp:ObjectDataSource runat="server" ID="ods" TypeName="MyDS" SelectMethod="Get" UpdateMethod="Update" DataObjectTypeName="Ent">
    </asp:ObjectDataSource>
    <asp:FormView runat="server" DefaultMode="Edit" ID="fv1" DataSourceID="ods">
        <EditItemTemplate>
            <uc1:WebUserControl ID="WebUserControl1" runat="server" />
            <asp:Button runat="server" CommandName="Update" Text="Update"/>
        </EditItemTemplate>
    </asp:FormView>

这里是 WebUserControl.ascx:

<asp:TextBox ID="txt1" runat="server" Text='<%# Bind("Name") %>' />

在 TextBox 中选择值时一切正常。 Bind 使用预期值填充文本框。但是,当按下“更新”按钮时,ObjectDataSource 的方法 Update 获取 Ent 实例,其名称为 null,而输入的文本是预期的。 只是为了测试,我已将文本框放入 .aspx 中,一切正常。

最后我通过反射器 FormView 进行了反编译,其中 ExtractRowValues 看起来失败了,因为它只迭代直接子级。有人知道如何处理子绑定吗?

【问题讨论】:

  • 我刚刚输入了同样的问题,你的问题出现了,我就在这里。我也试图在 formview 中对 ascx 控件的属性进行数据绑定并面临同样的问题。如果你知道了,请分享。
  • @The_AlienCoder 我已经被 Reflector 反汇编了——对于嵌套控件,updateTemplate 根本没有解析绑定语法。但是在 itemTemplate 中存在相同的语法,因此唯一的方法是覆盖 aspx 的解析。

标签: asp.net formview data-binding


【解决方案1】:

抱歉,有点晚了:-)

'绑定'是一头奇怪的野兽。无处没有 Bind 方法。它只是一个特定的 ASP.NET 令牌,它指示 ASP.NET 编译器在数据绑定上添加“Eval”调用(确实有一个Eval 方法),并为双向绑定生成一个特定的提取代码隐藏方法。

但这个方法只被添加(并在提取时调用)配备ITemplate 属性的控件(例如 FormView 的 ItemTemplate、EditItemTemplate 等),并且声明为可双向绑定。

不幸的是,对于用户控件(ascx),没有简单的方法可以生成这种方法。

但是,您可以在用户控件中实现 IBindableControl Interface,尽管它的自动化程度较低、声明性较差,但它允许一些集成,如下所示:

WebUserControl.ascx:

<asp:TextBox ID="txt1" runat="server" Text='<%# Eval("Name") %>' />

(注意 Bind 是无用的,所以你可以坚持使用 Eval)。

WebUserControl.ascx.cs:

public partial class WebUserControl : UserControl, IBindableControl
{
    public void ExtractValues(IOrderedDictionary dictionary)
    {
        dictionary["Name"] = txt1.Text;
    }
}

【讨论】:

  • 我不能立即尝试/检查你的想法,所以我会相信你的话,只回答一件事:“在文本框中选择值时一切正常。绑定填充文本框预期值。但是当按下按钮“更新”时,ObjectDataSource 的方法 Update 获取 Ent 的实例为 null“ - 那么在更新期间是否会调用 IBindableControl 方法?
  • @Dewfy - 是的,IBindableControl.ExtractValues 将由 FormView 命令处理程序调用(这不是一个想法,它实际上应该可以工作 :-)
【解决方案2】:

您必须将 语法从用户控件 (ASCX) 移动到包含页面 (ASPX) 并使用 属性在您的用户控件中获取和设置表单值。我下面的示例改编自 http://oudinia.blogspot.co.uk/2007/12/aspnet-20-and-up-c-user-control-within.html 给出的解决方案,并添加了更多细节以使其现实:

ASCX 标记:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="PaperForm.ascx.cs" Inherits="PaperForm" %>

<asp:ValidationSummary runat="server" HeaderText="<b>Please supply the missing information below.</b>" />

<p class="SectionHeading">Section A: Your Details</p>
<table border="1" width="100%">
  <tr>
    <td width="220px">Membership number</td>
    <td colspan="3"><asp:TextBox ID="txtMemNo" runat="server" MaxLength="9"></asp:TextBox>
        <asp:RegularExpressionValidator runat="server" ControlToValidate="txtMemNo" Display="Dynamic" Text="Please check your membership number" ValidationExpression="\d{9}"></asp:RegularExpressionValidator>
    </td>
  </tr>
  <tr>
    <td><asp:Label ID="lblFirstName" runat="server">First name</asp:Label></td>
    <td><asp:TextBox ID="txtForename" runat="server"></asp:TextBox>
        <asp:RequiredFieldValidator runat="server" ControlToValidate="txtForename" Text="Required"></asp:RequiredFieldValidator>
    </td>
    <td width="110px"><asp:Label ID="lblLastName" runat="server">Last name</asp:Label></td>
    <td><asp:TextBox ID="txtSurname" runat="server"></asp:TextBox>
        <asp:RequiredFieldValidator runat="server" ControlToValidate="txtSurname" Text="Required"></asp:RequiredFieldValidator>
    </td>
  </tr>
  ...
</table>

<script type="text/javascript" language="javascript">
  // perform additional client-side validation in JavaScript
  function ValidateForm()
  {
    // check membership number (via web-service)
    ...
  }
</script>

ASCX 代码隐藏:

public partial class PaperForm : UserControl
{
    // **public properties representing form data**
    public string MemNo { get { return txtMemNo.Text; } set { txtMemNo.Text = value; } }
    public string Forename { get { return txtForename.Text; } set { txtForename.Text = value; } }
    public string Surname { get { return txtSurname.Text; } set { txtSurname.Text = value; } }
    ...

    protected void Page_Load(object sender, EventArgs e)
    {
        // prevent browser caching
        ...
    }
}

ASPX 标记:

<%--register the user control here--%>
<%@ Register TagPrefix="UC" TagName="PaperForm" Src="~/Proposals/PaperForm.ascx" %>

<asp:FormView ID="fvPaper" runat="server" DataKeyNames="PprPropID" DataSourceID="tblPprProp" DefaultMode="Insert" Width="780px">    
  <InsertItemTemplate>

    <%--insert the user control here, **and bind the database fields to its properties**--%>
    <UC:PaperForm ID="pf" runat="server" MemNo='<%# Bind("MemNo") %>' Forename='<%# Bind("Forename") %>' Surname='<%# Bind("Surname") %>' ... />
    ...
    <%--can use the JavaScript ValidateForm() function defined in the ASCX file--%>
    <asp:Button ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Submit" BackColor="#C2D9EC" OnClientClick="return ValidateForm();" />
  </InsertItemTemplate>
</asp:FormView>

<%--define the data-source here rather than in the ASCX file--%>
<asp:SqlDataSource ID="tblPprProp" runat="server" ConflictDetection="CompareAllValues" ConnectionString="<%$ ConnectionStrings:confConnectionString %>" OnInserted="AfterInsertion" 
  InsertCommand="INSERT INTO [tblPprProp] ([MemNo], [Surname], [Forename], ...) VALUES (@MemNo, @Surname, @Forename, ...); SELECT @RowID = SCOPE_IDENTITY()" 
  OldValuesParameterFormatString="original_{0}">
  <InsertParameters>
    <asp:Parameter Name="MemNo" Type="String" />
    <asp:Parameter Name="Surname" Type="String" />
    <asp:Parameter Name="Forename" Type="String" />
    ...
  </InsertParameters>
</asp:SqlDataSource>

ASPX 代码隐藏:

public partial class PaperProposal : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    protected void AfterInsertion(object sender, SqlDataSourceStatusEventArgs e)
    {
        // get Proposal ID
        string rowId = e.Command.Parameters["@RowID"].Value.ToString();
        // get e-mail address from ASCX property
        string address = ((PaperForm)this.fvPaper.FindControl("pf")).Email;
        // send acknowledgement e-mail
        ...
    }
}

【讨论】:

  • 请仔细阅读我写的内容:“只是为了测试,我已将文本框放入 .aspx 中,一切正常”,所以很明显。您没有提供有关如何在 .ascx 中使用绑定的问题的答案。超出范围 - 如果您发布一些解决方案,请尽量减少样本,从上面的 4 个巨大列表中不清楚您在说什么。
  • 我第一次理解你是正确的;我的回答仍然有效。您想知道如何将 Bind() 语法与数据绑定用户控件一起使用,不是吗?我的回答是您不能在用户控件中拥有 Bind() 语法:您必须在包含的 ASPX 页面中拥有它并在用户控件中使用属性。我已经为您提供了 ASCX 和 ASPX 文件的示例,以展示它们如何结合在一起。很抱歉,如果您不喜欢我的回答 - 鉴于这是您提出问题后两年来您收到的唯一一个,我认为您的期望可能有点高。
  • 你的回答不成立——因为它是从前面已经说过的复制而来的。关于答案 - 我已经解决了这个问题,你可以在我的问题中看到它 - 所以这段时间没有任何期望。我想知道是否存在更优雅的解决方案。另外让我们假设一些新手会转到此页面 - 他/她无法从您的回答中得到任何有用的信息,因为您的列表很大。即使从这个角度来看,我也不能接受你的回答是正确和有帮助的。感谢您的关注,希望它不会冒犯您,多尝试,您将很快达到专家级。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 2011-03-03
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
相关资源
最近更新 更多