FormView на главной странице не может видеть элементы управления привязкой данных через границу ContentPlaceHolder - PullRequest
1 голос
/ 27 апреля 2009

У меня есть несколько схожих структур 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 ]

2 голосов
/ 30 апреля 2009

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

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

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

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

Только мои два цента

0 голосов
/ 05 мая 2009

Вот примерное решение - не изящное, но оно работает. В коде для 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.checked и т. д.).

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

0 голосов
/ 05 мая 2009

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

Возможно, вы захотите попробовать другой метод инкапсуляции вашего элемента управления 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 каждой страницы.

0 голосов
/ 01 мая 2009

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

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

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

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

0 голосов
/ 27 апреля 2009

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

...