Como criar uma caixa de texto somente leitura no ASP.NET MVC3 Razor


118

Como faço para criar uma caixa de texto somente leitura na ASP.NET MVC3 com o mecanismo de exibição Razor?

Existe um método HTMLHelper disponível para fazer isso?

Algo como o seguinte?

@Html.ReadOnlyTextBoxFor(m => m.userCode)

Respostas:


246
@Html.TextBoxFor(m => m.userCode, new { @readonly="readonly" })

Você pode criar um HTML Helper para isso, mas é simplesmente um atributo HTML como qualquer outro. Você faria um HTML Helper para uma caixa de texto com outros atributos?


1
@Shyju Desculpe, estava faltando o @prefixo da readonlypropriedade. Veja minha edição.

7
No futuro, se você receber qualquer tipo de erro ao adicionar propriedades ao argumento do objeto dinâmico, poderá prefixá-los com o @. Normalmente, você só o verá com palavras-chave que correspondam a atributos HTML (como somente leitura, classe etc.)
Brad Christie

10
@BradChristie: Não; você só precisa de um @para usar atributos que correspondam a palavras-chave C # .
SLaks

1
@BradChristie: Eu li errado seu comentário ("palavras-chave" era ambígua)
SLaks

1
Se você tiver vários atributos html, pode fazer algo como:@Html.TextBoxFor(m => m.userCode, new { @readonly="readonly", @class="form-control" })
benscabbia

32

ATUALIZAÇÃO: Agora é muito simples adicionar atributos HTML aos modelos de editor padrão. Isso significa em vez de fazer isso:

@Html.TextBoxFor(m => m.userCode, new { @readonly="readonly" })

você simplesmente pode fazer isso:

@Html.EditorFor(m => m.userCode, new { htmlAttributes = new { @readonly="readonly" } })

Benefícios: Você não tem que ligar .TextBoxFor, etc. para modelos. Basta ligar .EditorFor.


Embora a solução do @Shark funcione corretamente, e seja simples e útil, minha solução (que uso sempre) é esta: Criar um editor-templateque possa manipular o readonlyatributo :

  1. Crie uma pasta chamada EditorTemplatesem~/Views/Shared/
  2. Crie uma navalha PartialViewchamadaString.cshtml
  3. Preencha o String.cshtmlcom este código:

    @if(ViewData.ModelMetadata.IsReadOnly) {
        @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue,
            new { @class = "text-box single-line readonly", @readonly = "readonly", disabled = "disabled" })
    } else {
        @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue,
            new { @class = "text-box single-line" })
    }
  4. Na classe de modelo, coloque o [ReadOnly(true)]atributo nas propriedades que você deseja readonly.

Por exemplo,

public class Model {
    // [your-annotations-here]
    public string EditablePropertyExample { get; set; }

    // [your-annotations-here]
    [ReadOnly(true)]
    public string ReadOnlyPropertyExample { get; set; }
}

Agora você pode usar a sintaxe padrão do Razor simplesmente:

@Html.EditorFor(m => m.EditablePropertyExample)
@Html.EditorFor(m => m.ReadOnlyPropertyExample)

O primeiro renderiza um normal text-boxassim:

<input class="text-box single-line" id="field-id" name="field-name" />

E o segundo irá renderizar;

<input readonly="readonly" disabled="disabled" class="text-box single-line readonly" id="field-id" name="field-name" />

Você pode usar esta solução para qualquer tipo de dados ( DateTime, DateTimeOffset, DataType.Text, DataType.MultilineTexte assim por diante). Basta criar um editor-template.


2
+1 porque você usou "ViewData.ModelMetadata.IsReadOnly". Eu esperava que o MVC levasse em consideração essas coisas na versão 4.
cleftheris

@cleftheris bem, estamos na versão 5 agora, e MVC ainda não os aceitou;)
ravy amiry

2
@Javad_Amiry - ótima resposta - eu implementei e parecia funcionar muito bem até clicar em Salvar em uma página de edição de andaime. Em seguida, descobre-se que Propriedades com [ReadOnly (true)] resultará no envio de NULL ao banco de dados em vez do valor real da propriedade - você já encontrou isso?
Percy

5

A solução com TextBoxFor está OK, mas se você não quiser ver o campo como EditBox estiloso (pode ser um pouco confuso para o usuário), envolva as seguintes alterações:

  1. Código do Razor antes das mudanças

    <div class="editor-field">
         @Html.EditorFor(model => model.Text)
         @Html.ValidationMessageFor(model => model.Text)
    </div>
  2. Depois das mudanças

    <!-- New div display-field (after div editor-label) -->
    <div class="display-field">
        @Html.DisplayFor(model => model.Text)
    </div>
    
    <div class="editor-field">
        <!-- change to HiddenFor in existing div editor-field -->
        @Html.HiddenFor(model => model.Text)
        @Html.ValidationMessageFor(model => model.Text)
    </div>

Geralmente, esta solução impede que o campo seja editado, mas mostra o valor dele. Não há necessidade de modificações por trás do código.


1
Acho que ter o CSS para as classes editor-field e display-field pode ser realmente útil.
DOK

O que você quer dizer com "esta solução desativa o processo contra edição" (parece incompreensível)? Responda editando sua resposta , não aqui nos comentários (conforme apropriado).
Peter Mortensen de

3

Com os créditos da resposta anterior de @Bronek e @Shimmy:

É como se eu tivesse feito a mesma coisa no ASP.NET Core:

<input asp-for="DisabledField" disabled="disabled" />
<input asp-for="DisabledField" class="hidden" />

A primeira entrada é somente leitura e a segunda passa o valor para o controlador e fica oculta. Espero que seja útil para alguém que trabalha com ASP.NET Core.


0
 @Html.TextBox("Receivers", Model, new { @class = "form-control", style = "width: 300px", @readonly = "readonly" })

1
Uma explicação seria necessária.
Peter Mortensen de

0
@Html.TextBoxFor(model => model.IsActive, new { readonly= "readonly" })

Isso é adequado para caixa de texto. No entanto, se você tentar fazer o mesmo para o checkbox, tente usar isto se estiver usando:

@Html.CheckBoxFor(model => model.IsActive, new { onclick = "return false" })

Mas não use disable, porque desabilitar sempre envia o valor padrão falsepara o servidor - ou estava no estado marcado ou não. E readonlynão funciona para a caixa de seleção e radio button. readonlysó funciona para textcampos.


E as listas suspensas?
user3020047


0

Você pode usar o código a seguir para criar um TextBox como somente leitura.

Método 1

 @Html.TextBoxFor(model => model.Fields[i].TheField, new { @readonly = true })

Método 2

@Html.TextBoxFor(model => model.Fields[i].TheField, new { htmlAttributes = new {disabled = "disabled"}})
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.