2012-04-17 33 views
7

我有這樣的錯誤,當我嘗試更新一個FormView找不到在FormView控件(對於嵌套屬性雙向綁定)

名爲「xxx.yyy」屬性

找不到一個名爲「屬性MainContact .FirstName'在由ObjectDataSource 'odsForm'中的DataObjectTypeName屬性指定的類型 上。

我想這是因爲我在EditTemplate使用TextBox這樣

<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

我該如何解決這個問題?

回答

1

兩種可能的方法。

首先,您可以從ObjectDataSource的定義中刪除DataObjectTypeName="Helpers.BusinessObjects.EntryItem"。我從來沒有使用過,綁定始終有效。

但這種可能沒有用,因爲Bind/Eval可能不能遵循引用(Bind("MainContact.FirstName"))。

取而代之,重寫這個作爲

<%# ((EntryItem)Container.DataItem).MainContract.FirstName #> 

的缺點是,你失去的自動雙向綁定,所以你一定要幫粘結劑一點。只需添加一個Inserting/Updating處理程序到您的ObjectDataSource和內部處理程序:

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

根據幾個來源,這實際上是不可能做到雙向嵌套特性結合。

下面是對SO上類似問題的一個答案:https://stackoverflow.com/a/1195119/370671

此外,there's a blog post描述了這個問題:

現在,仍然在大多數情況下使用ObjectDataSource不會給你造成任何問題,當什麼[你]綁定是一個簡單的屬性,如客戶端即一個名字:您有一組綁定到GridView的客戶端,其中一列顯示客戶端的名稱。要做到這一點,你需要使用類似Bind("Name")的東西。當您需要綁定到子屬性時出現問題,如 Bind("Address.StreetName")。這將無法正常工作

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

然後,你將需要改變所有的GridView的,FormViews等存儲出生日期,否則框架將調用你的ObjectDataSource更新方法將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 
    } 
} 

這樣任何除了你的域名將是你的看法安全,數據對象將讀/寫只有他們需要的字段。

+0

+1:我總是會因爲ObjectDataSource而浪費時間,我只是希望下次我記得不要打擾他們。 – capdragon 2013-06-03 19:04:24