FormView em uma página mestre não pode ver databound controles através ContentPlaceHolder fronteira

StackOverflow https://stackoverflow.com/questions/791572

  •  16-09-2019
  •  | 
  •  

Pergunta

Eu tenho um número de FormViews de estrutura semelhante. Em um esforço para evitar a marcação duplicado, criei uma página mestra que contém o FormView, e colocou um ContentPlaceHolder dentro do FormView. Os controles específicos de ligação de dados - que são a única coisa que a mudança de página para página - são, em seguida, na página que usa essa página mestra

.

Então, eu tenho uma página mestra que é algo como isto:

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

e uma página usando essa página mestra que é algo como isto:

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

Com um registro existente, o FormView vê através dos controles de ligação de dados (campo1, etc) e preenche-los com os dados corretos. Mas quando inserir ou atualização, ele não vê-los, e eles não estão incluídos na inserção ou atualização. No caso FormView_ItemInserting, e.Values está vazio; Da mesma forma, no caso FormView_ItemUpdating, e.NewValues está vazio.

Assim:

  1. Existe uma maneira de provocar o FormView na página principal para ver através dos controles de ligação de dados dentro do contentplaceholder?

  2. Se isso falhar, há uma maneira simples de identificar os controles que são databound com <%#Bind(...)%> para que eu possa adicioná-los manualmente para o saco de valores?

Foi útil?

Solução

Eu acho que isso vai ser difícil, se não for possível; na verdade, eu estou surpreso que a ligação de dados funciona em tudo!

Você pode querer tentar um método diferente de encapsular o controle FormView.

Você poderia tentar colocar o controle FormView em um controle ascx com um espaço reservado onde agora você tem a ContentPlaceHolder.

Em seguida, em cada página ASPX, você poderia ter uma página ASCX espelho que contém o enchimento para o espaço reservado. Você poderia dar-lhes os mesmos nomes (Page1.aspx usa Page1.ascx) ou configurar uma convenção de nomenclatura como Página1-Content.ascx, para que seu ascx FormView iria descobrir o que de controle de enchimento é nomeado, o uso Page.LoadControl () para carregar o controlo pelo caminho, e ligá que o conteúdo em durante a fase de inicialização.

Agora, seus controles de conteúdo têm a vantagem de ser capaz de ter propriedades públicas, para que você possa ligar-se a essas propriedades públicas, e têm as propriedades shuttle os dados de e para os controles de servidor apropriadas no arquivo de enchimento .ascx.

Infelizmente é o dobro dos arquivos (por causa do ASPX e ASCX necessário para cada página), mas bastante trabalho-unintensive comparação com a alternativa (a duplicação de todo o código)

É claro que você não nos disse o que todos a sua marcação comum é, mas sua marcação comum poderia entrar em um CommonMarkupHeader.ascx e CommonMarkupFooter.ascx bem e incluído no FormView exclusivo de cada página.

Outras dicas

Há um par de coisas que vêm à mente porque esta configuração não funcionará e pode levar a mais de código de marcação.

Se você tem uma fonte de dados definida na página mestra não vai lidar com os diferentes dados controles ligados a partir de cada página sem adicionar mais lógica para a página principal para alterar a consulta etc.

Todas as vistas de formulário vão ser unidas com o aumento da complexidade das alterações no caminho

Eu iria com páginas separadas para cada FormView reduzir a complexidade do código, a depuração ea capacidade de mudança

Apenas meus dois centavos

Onde você tem forma de servidor tag? Pode estar no espaço reservado para conteúdo em vez da página principal, para que seus valores não enviar a página do servidor depois de enviar

Você pode ser capaz de fazer algo assim ...

Definir uma interface para as suas "páginas de dados" que tem uma assinatura de método que retorna uma fonte de dados bindable ..

public interface IFormViewChild {
   IEnumerable GetFormData();
}

Em seguida, você pode ter seus "páginas de dados" implementar essa interface ...

public class ChildDataPage : Page, IDataPage {
   public IEnumerable GetFormData() {
      // code to return stuff here
   }
}

Finalmente, na carga do seu masterpage () evento ...

if (Page is IFormViewChild) {
   myFormViewControl.DataSource = ((IFormViewChild)Page).GetFormData();
   myFormViewControl.DataBind();
}

Tenha em mente que este é todo o código psudo digitado diretamente para este editor de formulários web .. por isso é provavelmente errado. Mas pode não ser:)

Aqui está uma solução provisória - não elegante, mas funciona. No code-behind para Form.Master eu tenho algo ao longo destas linhas:

    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

Isto não é tão elegante, pois

  1. Eu tenho que saber os nomes de todos os controles de ligação de dados
  2. Esta baseia-se no pressuposto de que o ID de cada controle corresponde ao nome do campo
  3. A função 'GetValue' (não incluído aqui) é uma solução desajeitada: ele verifica vários tipos (caixa de texto, dropdownlist, caixa, etc.) e recebe o valor da cadeia da propriedade adequada (TextBox.Text, dropdownlist.selectedvalue , checkbox.checked, etc).

Eu ainda gostaria de ter pelo menos uma forma de saber o que está ligado com a '<% # Bind ( 'Foo')%>' sintaxe e obter essa informação diretamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top