我尝试更新FormView
时出现此错误无法在类型上找到名为“MainContact.FirstName”的属性 由ObjectDataSource中的DataObjectTypeName属性指定 'odsForm'。
我认为这是因为我在EditTemplate中使用了像这样的文本框
<asp:TextBox Text='<%# Bind("MainContact.FirstName") %>' ID="txtFirstName" runat="server" />
它在文本框中显示正确的文本,但显然它在更新时不起作用。
这是FormView的数据源
<asp:ObjectDataSource ID="odsForm" runat="server" DataObjectTypeName="Helpers.BusinessObjects.EntryItem"
SelectMethod="GetEntryByEmail" TypeName="Helpers.DataAccessers.EntryHelper"
UpdateMethod="UpdateEntry">
<SelectParameters>
<asp:SessionParameter SessionField="email" Name="email" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
这是EntryItem类
public class EntryItem
{
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public Person MainContact { get; set; }
...
}
和人类
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
...
}
调试器进入FormView ItemUpdating
事件处理程序,但永远不会进入Helpers.DataAccessers.EntryHelper.UpdateEntry
。
我该如何解决这个问题?
答案 0 :(得分:4)
您可以根据需要编写自己的控件来执行绑定,以这种方式使用(我做了其中一个):
<ItemTemplate>
<%# Eval("MainContact.FirstName")%>
</ItemTemplate>
<EditItemTemplate>
<xx:BinderHelper runat="server" DataSource='<%# Bind("MainContact") %>'>
<ItemTemplate>
<asp:TextBox Text='<%# Bind("FirstName") %>' ID="txtFirstName"
runat="server" />
</ItemTemplate>
</xx:BinderHelper>
</EditItemTemplate>
无论如何,我建议你不要直接在页面中使用域对象,并且整体不要用ObjectDataSource 来编写它们。问题是,当您更改域名时,例如添加字段:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// just added
public DateTime? BirthDate { get; set; }
}
然后,您需要更改所有GridViews,FormViews等以存储BirthDate,否则框架将调用您的ObjectDataSource Update方法将null
放在BirthDate中。例如:
<asp:GridView runat="server" DataSourceID="odsForm" AutoGenerateColumns="False">
<Columns>
<asp:CommandField runat="server" ShowEditButton="True" />
<asp:BoundField DataField="FirstName" />
<asp:BoundField DataField="LastName" />
</Columns>
</asp:GridView>
它将从数据库中读取您的人员。每个人都有一个出生日期。保存时,此人将使用BirthDate更新为null
,因为GridView不会存储新字段。
我认为最好的解决方案是编写DTO用于数据绑定(并将它们保留在表示层中)和DataObjects。在你的情况下:
public class EntryItemView
{
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string MainContactFirstName { get; set; }
}
[DataObject]
public class EntryItemViewDataObject {
[DataObjectMethod(DataObjectMethodType.Select)]
public EntryItemView GetItem(...) {
// TODO: read from the database, convert to DTO
}
[DataObjectMethod(DataObjectMethodType.Update)]
public void Update( EntryItemView entry) {
EntryItem domainObject = getById(entry.Id);
// TODO: use EmitMapper or AutoMapper
domainObject.MainContact.FirstName = entry.MainContactFirstName;
// TODO: save
}
}
通过这种方式,对域的任何添加对您的视图都是安全的,DataObjects将只读取/写入他们需要的字段。
答案 1 :(得分:1)
两种可能的方法。
首先,您可以从DataObjectTypeName="Helpers.BusinessObjects.EntryItem"
的定义中删除ObjectDataSource
。我从来没有使用它,绑定总是有效。
但这可能无济于事,因为Bind/Eval
可能无法关注引用(Bind("MainContact.FirstName")
)。
相反,将其重写为
<%# ((EntryItem)Container.DataItem).MainContract.FirstName #>
缺点是你松开了自动双向绑定,所以你必须帮助一点点粘合剂。只需向ObjectDataSource和内部处理程序添加Inserting/Updating
处理程序:
protected void TheObjectDataSource_Updating( object sender, BlahBlahEventArgs e )
{
// find the control in the data bound parent
TextBox txt = (TextBox)YourFormView.FindControl( "txtFirstName" );
// read the value and add it to parameters
e.Parameters.Add( "nameofyourparameter", txt.Text );
}
答案 2 :(得分:0)
根据一些消息来源,实际上不可能使用嵌套属性进行双向绑定。
以下是关于SO的类似问题的一个答案:https://stackoverflow.com/a/1195119/370671。
此外,there's a blog post描述了这个问题:
现在,在大多数情况下使用
ObjectDataSource
仍然不会导致任何问题,当你绑定的是一个简单的属性,例如客户端的名称,即:你有一组绑定到的客户端一个GridView
,其中一列显示客户端的名称。为此,您可以使用Bind("Name")
之类的内容。当您需要绑定到子属性(如in)时会出现问题Bind("Address.StreetName")
。这不起作用