母版页上的FormView无法通过ContentPlaceHolder边界查看数据绑定控件

时间:2009-04-26 20:40:46

标签: asp.net master-pages formview

我有许多类似结构的FormView。为了避免重复标记,我创建了一个包含FormView的母版页,并在FormView中放置了一个ContentPlaceHolder。然后,特定的数据绑定控件(这是页面之间唯一的变化)将在使用该母版页的页面上。

所以我有一个看起来像这样的母版页:

<%@ master ... %>
...
<form runat=server>
...
   <asp:formview runat="server" ... >
      <edititemtemplate>
         ... Lots of common markup ...
         <asp:contentplaceholder id='FormRows' runat='server' />
         ... Lots more common markup ...
       </edititemtemplate>
    </asp:formview>
...
</form>

以及使用该主页的页面,如下所示:

<%@ page masterpagefile="Form.Master" ... %>
<asp:content contentplaceholderid="FormRows" runat="server" >
   ...
   <p>
     Field One: 
     <asp:textbox runat=server text='<%#Bind("Field1")%>' id='Field1' />
   </p>
   <p>
     Field Two: 
     <asp:textbox runat=server text='<%#Bind("Field2")%>' id='Field2' />
   </p>
   ...
</asp:content>

使用现有记录,FormView会看到数据绑定控件(Field1等)并使用正确的数据填充它们。但是在插入或更新时,它看不到它们,并且它们不包含在插入或更新中。在FormView_ItemInserting事件中,e.Values为空;同样在FormView_ItemUpdating事件中,e.NewValues为空。

所以:

  1. 有没有办法在母版页上激发FormView以查看ContentPlaceholder中的数据绑定控件?

  2. 如果失败了,是否有一种直接的方法来识别与<%#Bind(...)%>数据绑定的控件,以便我可以手动将它们添加到值包中?

5 个答案:

答案 0 :(得分:2)

有一些事情可以解释为什么这个设置不起作用,并且可能导致代码比标记更多。

如果您在母版页中定义了数据源,则它不会处理每个页面的不同数据绑定控件,而不会向母版页添加更多逻辑以更改查询等。

所有表单视图将耦合在一起,增加了变化的复杂性

我会为每个FormView使用单独的页面,以减少代码的复杂性,调试和更改的能力

只是我的两分钱

答案 1 :(得分:0)

你在哪里有服务器表格标签?可能在内容占位符而不是母版页中,因此您的值不会在提交后发送到服务器页面

答案 2 :(得分:0)

您可以做这样的事情......

为“数据页”定义一个接口,该接口具有返回可绑定数据源的方法签名。

public interface IFormViewChild {
   IEnumerable GetFormData();
}

然后你可以让你的“数据页面”实现该界面......

public class ChildDataPage : Page, IDataPage {
   public IEnumerable GetFormData() {
      // code to return stuff here
   }
}

最后,在您的母版页的Load()事件......

if (Page is IFormViewChild) {
   myFormViewControl.DataSource = ((IFormViewChild)Page).GetFormData();
   myFormViewControl.DataBind();
}

请记住,这是直接在此Web表单编辑器中键入的所有psudo代码..所以它可能是错误的。但它可能不是:)

答案 3 :(得分:0)

我认为如果不可能的话,这将是困难的;事实上,我很惊讶数据绑定的工作原理!

您可能希望尝试封装FormView控件的其他方法。

你可以尝试将FormView控件放在带有PlaceHolder的.ascx控件中,你现在拥有了ContentPlaceHolder。

然后在每个ASPX页面上,您可以拥有一个镜像ASCX页面,其中包含占位符的填充符。您可以为它们指定相同的名称(Page1.aspx使用Page1.ascx)或设置类似Page1-Content.ascx的命名约定,以便FormView ascx能够确定其填充控件的名称,使用Page.LoadControl()通过路径加载控件,并在Init阶段插入该内容。

现在,您的内容控件具有能够拥有公共属性的优势,因此您可以绑定到这些公共属性,并使属性将数据传送到填充.ascx文件中的相应服务器控件。 / p>

不幸的是,这是文件的两倍(因为每个页面都需要ASPX和ASCX),但与替代方案(复制所有代码)相比,工作非常繁琐

当然,您还没有告诉我们您的所有常见标记是什么,但您的常见标记也可以进入CommonMarkupHeader.ascx和CommonMarkupFooter.ascx,并包含在每个页面的唯一FormView中。

答案 4 :(得分:0)

这是一个临时解决方案 - 不优雅,但它有效。在Form.Master的代码隐藏中,我有以下几点:

    Private Sub FormView1_ItemInserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewInsertEventArgs) Handles FormView1.ItemInserting
        ManuallyAddValues(e.Values)
    End Sub

    Private Sub FormView1_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewUpdateEventArgs) Handles FormView1.ItemUpdating
        ManuallyAddValues(e.NewValues)
    End Sub

    Private Sub ManuallyAddValues(ByRef Values As IOrderedDictionary)
        For Each Field As Core.Field In FormView1.DataSourceControl.IncludedFields
            If Values(Field.Name) Is Nothing Then
                Dim DataboundControl As Control = FormView1.FindControl("FormRows").FindControl(Field.Name)
                Values.Add(Field.Name, GetValue(DataboundControl))
            End If
        Next
    End Sub

这不是那么优雅,因为

  1. 我必须知道所有数据绑定控件的名称
  2. 这依赖于每个控件的ID与fieldname
  3. 匹配的假设
  4. 'GetValue'函数(此处未包含)是一个笨拙的解决方案:它检查各种类型(文本框,下拉列表,复选框等)并从相应的属性中获取字符串值(textbox.text,dropdownlist.selectedvalue ,checkbox.checked等)。
  5. 我仍然喜欢至少知道与'&lt;%#Bind(“Foo”)%&gt;'绑定的内容。语法并直接获取该信息。