Не удалось найти свойство с именем «xxx.yyy» в FormView (двусторонняя привязка для вложенных свойств)

У меня ошибка при попытке обновить FormView

  

Не удалось найти свойство с именем 'MainContact.FirstName' для типа   указывается свойством DataObjectTypeName в ObjectDataSource   '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.

Как я могу решить эту проблему?

7 голосов | спросил Vinzcent 17 PMpTue, 17 Apr 2012 17:01:47 +040001Tuesday 2012, 17:01:47

3 ответа


0

Вы могли бы написать свой собственный элемент управления, способный выполнять привязку, как вы хотите, чтобы использовать его таким образом (я сделал одно из этого):

    <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, в противном случае платформа вызовет ваш метод Update ObjectDataSource, поместив null в дате рождения. Например:

<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 будет читать /писать только те поля, которые им нужны.

ответил onof 24 AM000000110000004731 2012, 11:10:47
0

Два возможных подхода.

Во-первых, вы можете удалить DataObjectTypeName="Helpers.BusinessObjects.EntryItem" из определения вашего ObjectDataSource. Я НИКОГДА не использовал это, и привязки всегда работают.

Но это, вероятно, не поможет, так как 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 );
}
ответил Wiktor Zychla 21 PM000000100000004031 2012, 22:25:40
0

Согласно нескольким источникам, на самом деле невозможно выполнить двустороннее связывание с вложенными свойствами.

Вот один ответ на аналогичный вопрос здесь, в SO: https://stackoverflow.com/a/1195119/370671.

Кроме того, есть запись в блоге описание проблемы:

  

Теперь, по-прежнему, в большинстве случаев использование ObjectDataSource не вызовет никаких проблем, когда [you] bind является простым свойством, таким как имя клиента, то есть: у вас есть набор клиентов, которые вы связываете с GridView, и в одном из столбцов отображается имя клиент. Для этого вы используете что-то вроде Bind("Name"). Проблема возникает, когда вам нужно привязать к подвойству, например, в   Bind("Address.StreetName"). Это не сработает

ответил Ryan Kohn 21 PM000000100000002631 2012, 22:38:26

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132