2012-04-17 13 views
7

Ho questo errore quando provo ad aggiornare un FormViewImpossibile trovare una proprietà denominata 'xxx.yyy' in FormView (legame a due vie per le proprietà nidificate)

Impossibile trovare una proprietà denominata 'MainContact .FirstName 'sul tipo specificato dalla proprietà DataObjectTypeName in ObjectDataSource ' odsForm '.

penso che sia perché io uso nel EditTemplate una casella di testo come questo

<asp:TextBox Text='<%# Bind("MainContact.FirstName") %>' ID="txtFirstName" runat="server" /> 

Essa mostra il testo a destra nella casella di testo, ma a quanto pare non funziona quando si aggiorna.

Questa è l'origine dati del 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> 

Questa è l'EntryItem Classe

public class EntryItem 
    { 
     public int Id { get; set; } 
     public string Email { get; set; } 
     public string Password { get; set; } 
     public Person MainContact { get; set; } 
     ... 
    } 

e la classe persona

public class Person 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    ... 
} 

Il debugger ottiene nel gestore di eventi FormView ItemUpdating , ma mai in Helpers.DataAccessers.EntryHelper.UpdateEntry.

Come posso risolvere questo?

risposta

1

Due possibili approcci.

Innanzitutto, è possibile eliminare DataObjectTypeName="Helpers.BusinessObjects.EntryItem" dalla definizione del proprio ObjectDataSource. Non l'ho mai usato e le associazioni funzionano sempre.

Ma questo probabilmente non aiuterà, poiché lo Bind/Eval probabilmente non è in grado di seguire i riferimenti (Bind("MainContact.FirstName")).

Invece, riscrivere questo come

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

Lo svantaggio è che perdi bidirezionale automatico vincolante quindi bisogna aiutare il legante un po '. Basta aggiungere un Inserting/Updating gestori al vostro ObjectDataSource e dentro i gestori:

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

Secondo un paio di fonti, in realtà non è possibile fare di legame con le proprietà nidificate a due vie.

Ecco una risposta a una domanda simile qui su SO: https://stackoverflow.com/a/1195119/370671.

Inoltre, there's a blog post che descrive il problema:

Ora, ancora, nella maggior parte dei casi utilizzando ObjectDataSource non causa alcun problema quando ciò che [si] bind è una struttura semplice come il nome di un esempio client: si dispone di una raccolta di client che si associa a un GridView e una delle colonne visualizza il nome del client. Per fare ciò usate qualcosa come Bind("Name"). Il problema sorge quando è necessario eseguire il binding a una sottoproprietà come in Bind("Address.StreetName").Questo non funzionerà

4

Si potrebbe scrivere il proprio controllo in grado di svolgere vincolante come si vuole, per essere utilizzato in questo modo (ho fatto uno di questo):

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

Ad ogni modo, io vi suggerisco non utilizzare oggetti di dominio direttamente nelle pagine, e nel complesso non scrivere loro con ObjectDataSource. Il problema è che quando si cambierà il dominio, ad esempio per aggiungere un campo:

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

Poi sarà necessario cambiare tutte le GridView, FormViews, ecc per memorizzare la data di nascita, altrimenti il ​​quadro chiamerà l'ObjectDataSource Metodo di aggiornamento che inserisce null nel Birth Date. Ad esempio:

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

Legge le persone dal database. Ogni persona avrà una data di nascita impostata. Quando si salva, la persona verrà aggiornata con BirthDate a null, poiché GridView non memorizza il nuovo campo.

Penso che la soluzione migliore sia scrivere DTO per il databinding (e lasciarli nel Presentation Layer) e DataObjects. Nel tuo caso:

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

In questo modo qualsiasi aggiunta al dominio non comporti rischi per le vostre opinioni, e DataObjects leggeranno/scrivere solo i campi di cui hanno bisogno.

+0

+1: Mi brucia sempre sprecando il mio tempo con 'ObjectDataSource'. Spero solo che la prossima volta mi ricordi di non preoccuparmi di loro. – capdragon

Problemi correlati