内部 .ascx 控件和 FormView 中的数据绑定

发布于 2024-08-26 17:28:40 字数 974 浏览 13 评论 0原文

我在 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") %>' />

在将值选择到文本框中时,一切正常。绑定用预期值填充文本框。但是,当按下“Update”按钮时,ObjectDataSource 的方法 Update 会获取带有 null 而不是 Name 的 Ent 实例,而需要输入文本。 只是为了测试,我已将文本框放入 .aspx 中,一切正常。

最后,我通过反射器 FormView 进行反编译,其中 ExtractRowValues 看起来失败,因为仅迭代直接子项。有人知道如何解决子绑定问题吗?

I have ascx control inside FormView. What I would like is use syntax Bind inside ascx.
Here is my page:

    <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>

Here is WebUserControl.ascx:

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

On selecting values into the TextBox everything works fine. Bind populates textbox with expected value. But when button "Update" pressed the ObjectDataSource's method Update gets instance of Ent with null instead Name, while entered text is expected.
Just for test I have placed textbox into the .aspx and everything works fine.

At last I have decompiled by reflector FormView, where ExtractRowValues looks failed since iterates only over direct children. Does anybody know how to work around with child bindings?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ˉ厌 2024-09-02 17:28:40

抱歉,如果这有点晚了:-)

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

但此方法仅针对配备 ITemplate 属性(例如 FormView 的 ItemTemplate、EditItemTemplate 等),并且声明为可双向绑定。

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

但是,您可以使用 IBindableControl 接口可以在允许某些集成的用户控件中实现,尽管它的自动性和声明性较低,如下所示:

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;
    }
}

Sorry if this is a bit late :-)

'Bind' is a strange beast. There is no Bind method nowhere. It's just a specific ASP.NET token that instructs the ASP.NET compiler to adds 'Eval' call (there is an Eval method indeed) on databinding and generates a specific extraction code hidden method for dual way binding.

But this method is only added (and called on extraction) for controls that are equipped with ITemplate properties (such as FormView's ItemTemplate, EditItemTemplate, etc...), and that are declared two-ways bindable.

Unfortunately, for a user control (an ascx), there is no easy way to have that kind of method generated.

However, there is the IBindableControl Interface that you could implement in the user control that allows some integration although it's less automatic, less declarative, like this:

WebUserControl.ascx:

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

(Note the Bind is useless so you can just stick with Eval).

WebUserControl.ascx.cs:

public partial class WebUserControl : UserControl, IBindableControl
{
    public void ExtractValues(IOrderedDictionary dictionary)
    {
        dictionary["Name"] = txt1.Text;
    }
}
樱桃奶球 2024-09-02 17:28:40

您必须将 <%# Bind("") %> 语法从用户控件 (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
        ...
    }
}

You have to move the <%# Bind("") %> syntax from the user control (ASCX) to the containing page (ASPX) and use properties in your user control to get and set the form values. My example below is adapted from the solution given at http://oudinia.blogspot.co.uk/2007/12/aspnet-20-and-up-c-user-control-within.html with a few more details to try to make it realistic:

ASCX mark-up:

<%@ 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 code-behind:

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 mark-up:

<%--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 code-behind:

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
        ...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文