Suponha que eu tenha o ViewModel como
public class AnotherViewModel
{
public string Name { get; set; }
}
public class MyViewModel
{
public string Name { get; set; }
public AnotherViewModel Child { get; set; }
public AnotherViewModel Child2 { get; set; }
}
Na visão, posso renderizar parcial com
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
No parcial eu vou fazer
<%= Html.TextBox("Name", Model.Name) %>
or
<%= Html.TextBoxFor(x => x.Name) %>
No entanto, o problema é que ambos renderizarão name = "Name" enquanto eu preciso ter name = "Child.Name" para que o fichário do modelo funcione corretamente. Ou, name = "Child2.Name" quando eu renderizar a segunda propriedade usando a mesma exibição parcial.
Como faço para que minha visualização parcial reconheça automaticamente o prefixo necessário? Eu posso passar isso como um parâmetro, mas isso é muito inconveniente. Isso é ainda pior quando eu quero, por exemplo, renderizá-lo recursivamente. Existe uma maneira de renderizar visões parciais com um prefixo ou, melhor ainda, com a reconciliação automática da expressão lambda de chamada para que
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
adicionará automaticamente "Filho" correto. prefixo para as cadeias de nome / ID geradas?
Posso aceitar qualquer solução, incluindo mecanismos e bibliotecas de exibição de terceiros - eu realmente uso o Spark View Engine (eu "resolvo" o problema usando suas macros) e o MvcContrib, mas não encontrei uma solução lá. XForms, InputBuilder, MVC v2 - qualquer ferramenta / insight que forneça essa funcionalidade será excelente.
Atualmente, penso em codificar isso sozinho, mas parece uma perda de tempo, não acredito que esse material trivial ainda não esteja implementado.
Muitas soluções manuais podem existir e todas são bem-vindas. Por exemplo, eu posso forçar minhas parciais a serem baseadas em IPartialViewModel <T> {public string Prefix; Modelo T; } Mas prefiro uma solução existente / aprovada.
ATUALIZAÇÃO: há uma pergunta semelhante sem resposta aqui .
helper.ViewData.TemplateInfo.HtmlFieldPrefix
no formato de{oldprefix}.{newprefix}
new ViewDataDictionary(helper.ViewData)
pornew ViewDataDictionary(((HtmlHelper)helper).ViewData)
. Você vê algum problema com isso?string oldPrefix = helper.ViewData.TemplateInfo.HtmlFieldPrefix; if (oldPrefix != "") name = oldPrefix + "." + name;
Até agora, eu estava procurando a mesma coisa que encontrei neste post recente:
http://davybrion.com/blog/2011/01/prefixing-input-elements-of-partial-views-with-asp-net-mvc/
fonte
ViewDataDictionary
construtor que leva a correnteViewData
, ou você vai perder erros modelo de estado, dados de validação, etc.Minha resposta, baseada na resposta de Mahmoud Moravej, incluindo o comentário de Ivan Zlatev.
Edit: A resposta do Mohamoud está incorreta para renderização parcial aninhada. Você precisa anexar o novo prefixo ao prefixo antigo, apenas se for necessário. Isso não ficou claro nas respostas mais recentes (:
fonte
Usando o MVC2, você pode conseguir isso.
Aqui está a visão fortemente tipada:
Aqui está a exibição fortemente tipada para a classe filho (que deve ser armazenada em uma subpasta do diretório de exibição chamada EditorTemplates):
Aqui está o controlador:
Aqui estão as classes personalizadas:
E a fonte de saída:
Agora isso está completo. Defina um ponto de interrupção na ação Criar controlador de postagem para verificar. No entanto, não use isso com listas, porque não funcionará. Veja minha pergunta sobre o uso de EditorTemplates com IEnumerable para obter mais informações.
fonte
Html.EditorFor
método para renderizar o formulário filho. É exatamente para isso que os modelos de editor devem ser usados. Essa deve ser a resposta.Essa é uma pergunta antiga, mas para quem chega aqui procurando uma solução, considere usar
EditorFor
, conforme sugerido em um comentário em https://stackoverflow.com/a/29809907/456456 . Para passar de uma vista parcial para um modelo de editor, siga estas etapas.Verifique se sua visualização parcial está vinculada ao ComplexType .
Mova sua exibição parcial para uma subpasta EditorTemplates da pasta de exibição atual ou para a pasta Shared . Agora, é um modelo de editor.
Mude
@Html.Partial("_PartialViewName", Model.ComplexType)
para@Html.EditorFor(m => m.ComplexType, "_EditorTemplateName")
. O modelo do editor é opcional se for o único modelo para o tipo complexo.Os elementos de entrada HTML serão nomeados automaticamente
ComplexType.Fieldname
.fonte
PartailFor para asp.net Core 2, caso alguém precise.
fonte
Também deparei com esse problema e, depois de muita dor, achei mais fácil redesenhar minhas interfaces, de modo que não precisei postar novamente objetos de modelo aninhados. Isso me forçou a alterar meus fluxos de trabalho de interface: agora eu exijo que o usuário execute em duas etapas o que eu sonhava em uma, mas a usabilidade e a manutenção do código da nova abordagem são de maior valor para mim agora.
Espero que isso ajude alguns.
fonte
Você pode adicionar um auxiliar para o RenderPartial que pega o prefixo e o exibe no ViewData.
Em seguida, outro auxiliar que concatena o valor ViewData
e assim na visão ...
no parcial ...
fonte
Como você, adiciono a propriedade Prefix (uma string) aos meus ViewModels, os quais anexo antes dos nomes de entrada associados ao meu modelo. (YAGNI impedindo o abaixo)
Uma solução mais elegante pode ser um modelo de vista de base que tenha essa propriedade e alguns HtmlHelpers que verificam se o modelo de vista deriva dessa base e, em caso afirmativo, anexa o prefixo ao nome da entrada.
Espero que ajude,
Dan
fonte
Que tal antes de ligar para RenderPartial, você
Então no seu parcial você tem
fonte