FormView на главной странице не может видеть элементы управления с привязкой к данным через границу ContentPlaceHolder

У меня есть несколько схожим образом структурированных FormViews. Чтобы избежать дублирования разметки, я создал главную страницу, которая содержит FormView, и поместил ContentPlaceHolder внутри FormView. Конкретные элементы управления привязкой к данным - которые единственные, которые меняются от страницы к странице - затем находятся на странице, которая использует эту главную страницу.

Итак, у меня есть главная страница, которая выглядит примерно так:

<%@ 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 ответов

Решение

Я думаю, что это будет трудно, если не возможно; на самом деле я удивлен, что привязка данных работает вообще!

Вы можете попробовать другой метод инкапсуляции вашего элемента управления FormView.

Вы можете попробовать поместить элемент управления FormView в элемент управления.ascx с помощью PlaceHolder, где у вас теперь есть ContentPlaceHolder.

Затем на каждой странице ASPX вы можете иметь зеркальную страницу ASCX, которая содержит заполнитель для заполнителя. Вы могли бы дать им одинаковые имена (Page1.aspx использует Page1.ascx) или установить соглашение об именах, например Page1-Content.ascx, чтобы ваш FormView ascx выяснил, как назван его элемент управления заполнителем, используйте Page.LoadControl() загрузить элемент управления по пути и подключить этот контент на этапе инициализации.

Теперь у ваших элементов управления контентом есть то преимущество, что они могут иметь общедоступные свойства, так что вы можете связываться с этими общедоступными свойствами, а свойства переносить данные в соответствующие серверные элементы управления в файле заполнителя.ascx и обратно.

К сожалению, это вдвое больше файлов (из-за ASPX и ASCX, необходимых для каждой страницы), но довольно трудоемкий по сравнению с альтернативой (дублирование всего этого кода)

Конечно, вы не сказали нам, какова вся ваша общая разметка, но ваша общая разметка может также входить в CommonMarkupHeader.ascx и CommonMarkupFooter.ascx и включаться в уникальный FormView каждой страницы.

Есть несколько вещей, которые приходят на ум, почему эта установка не будет работать и может привести к большему количеству кода, чем разметка.

Если у вас есть источник данных, определенный на главной странице, он не будет обрабатывать различные элементы управления, привязанные к данным на каждой странице, без добавления дополнительной логики на главную страницу для изменения запроса и т. Д.

Все виды форм будут связаны вместе, что усложнит внесение изменений в будущем

Я бы пошел с отдельными страницами для каждого FormView, уменьшая сложность кода, отладку и возможность изменения

Просто мои два цента

Где у вас есть серверная форма тега? Может быть в содержании заполнен главной страницей, поэтому ваши значения не отправляются на страницу сервера после отправки

Вот примерное решение - не элегантно, но оно работает. В коде для 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. Это основано на предположении, что идентификатор каждого элемента управления соответствует имени поля
  3. Функция "GetValue" (здесь не включена) является неуклюжим решением: она проверяет различные типы (текстовое поле, выпадающий список, флажок и т. Д.) И получает строковое значение из соответствующего свойства (textbox.text, dropdownlist.selectedvalue, checkbox. проверено и т. д.).

Я все еще хотел бы иметь хотя бы способ узнать, что связано с синтаксисом<<# # Bind ("Foo")%>и получать эту информацию напрямую.

Вы могли бы сделать что-то вроде этого...

Определите интерфейс для ваших "страниц данных", который имеет сигнатуру метода, которая возвращает привязываемый источник данных.

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

Пожалуйста, имейте в виду, что это весь псевдо-код, введенный непосредственно в этот редактор веб-форм... так что это, вероятно, неправильно Но это не может быть:)

Другие вопросы по тегам