Adicionar uma coluna de GridView de botões de opção (VB)
por Scott Mitchell
Este tutorial analisa como adicionar uma coluna de botões de opção a um controle GridView para fornecer ao usuário uma maneira mais intuitiva de selecionar uma única linha do GridView.
Introdução
O controle GridView oferece uma grande quantidade de funcionalidades internas. Ele inclui vários campos diferentes para exibir texto, imagens, hiperlinks e botões. Ele dá suporte a modelos para personalização adicional. Com alguns cliques do mouse, é possível fazer um GridView em que cada linha pode ser selecionada por meio de um botão ou habilitar a edição ou exclusão de recursos. Apesar da infinidade de recursos fornecidos, muitas vezes haverá situações em que recursos adicionais e sem suporte precisarão ser adicionados. Neste tutorial e nos próximos dois, examinaremos como aprimorar a funcionalidade do GridView para incluir recursos adicionais.
Este tutorial e o próximo se concentram em aprimorar o processo de seleção de linha. Conforme examinado no Mestre/Detalhe usando um Selectable Master GridView com um Details DetailView, podemos adicionar um CommandField ao GridView que inclui um botão Selecionar. Quando clicado, um postback é seguido e a propriedade gridView é SelectedIndex
atualizada para o índice da linha cujo botão Selecionar foi clicado. No tutorial Mestre/Detalhes Usando um GridView Mestre Selecionável com um DetailView de Detalhes , vimos como usar esse recurso para exibir detalhes da linha GridView selecionada.
Embora o botão Selecionar funcione em muitas situações, ele pode não funcionar tão bem para outras pessoas. Em vez de usar um botão, dois outros elementos da interface do usuário são comumente usados para seleção: o botão de opção e a caixa de seleção. Podemos aumentar o GridView para que, em vez de um botão Selecionar, cada linha contenha um botão de opção ou caixa de seleção. Em cenários em que o usuário só pode selecionar um dos registros gridView, o botão de opção pode ser preferido em vez do botão Selecionar. Em situações em que o usuário pode potencialmente selecionar vários registros, como em um aplicativo de email baseado na Web, em que um usuário pode querer selecionar várias mensagens para excluir a caixa de seleção oferece funcionalidade que não está disponível nas interfaces do usuário do botão Selecionar ou botão de opção.
Este tutorial analisa como adicionar uma coluna de botões de opção ao GridView. O tutorial de continuação explora o uso de caixas de seleção.
Etapa 1: Criando o aprimoramento das páginas da Web gridView
Antes de começarmos a aprimorar o GridView para incluir uma coluna de botões de opção, vamos primeiro tirar um momento para criar as páginas ASP.NET em nosso projeto de site que precisaremos para este tutorial e as próximas duas. Comece adicionando uma nova pasta chamada EnhancedGridView
. Em seguida, adicione as seguintes ASP.NET páginas a essa pasta, certificando-se de associar cada página à Site.master
página master:
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
Figura 1: Adicionar as páginas de ASP.NET para os tutoriais do SqlDataSource-Related
Assim como nas outras pastas, Default.aspx
na EnhancedGridView
pasta listará os tutoriais em sua seção. Lembre-se de que o SectionLevelTutorialListing.ascx
Controle de Usuário fornece essa funcionalidade. Portanto, adicione esse Controle de Usuário ao Default.aspx
arrastando-o do Gerenciador de Soluções para o modo design da página.
Figura 2: Adicionar o controle de SectionLevelTutorialListing.ascx
usuário a Default.aspx
(clique para exibir a imagem em tamanho real)
Por fim, adicione essas quatro páginas como entradas ao Web.sitemap
arquivo. Especificamente, adicione a seguinte marcação após Usar o controle <siteMapNode>
SqlDataSource :
<siteMapNode
title="Enhancing the GridView"
url="~/EnhancedGridView/Default.aspx"
description="Augment the user experience of the GridView control.">
<siteMapNode
url="~/EnhancedGridView/RadioButtonField.aspx"
title="Selection via a Radio Button Column"
description="Explore how to add a column of radio buttons in the GridView." />
<siteMapNode
url="~/EnhancedGridView/CheckBoxField.aspx"
title="Selection via a Checkbox Column"
description="Select multiple records in the GridView by using a column of
checkboxes." />
<siteMapNode
url="~/EnhancedGridView/InsertThroughFooter.aspx"
title="Add New Records through the Footer"
description="Learn how to allow users to add new records through the
GridView's footer." />
</siteMapNode>
Depois de atualizar Web.sitemap
, reserve um momento para exibir o site de tutoriais por meio de um navegador. O menu à esquerda agora inclui itens para os tutoriais de edição, inserção e exclusão.
Figura 3: O mapa do site agora inclui entradas para os tutoriais de Aprimoramento do GridView
Etapa 2: Exibindo os fornecedores em um GridView
Para este tutorial, vamos criar um GridView que lista os fornecedores dos EUA, com cada linha GridView fornecendo um botão de opção. Depois de selecionar um fornecedor por meio do botão de opção, o usuário pode exibir os produtos do fornecedor clicando em um botão. Embora essa tarefa possa soar trivial, há uma série de sutilezas que a tornam particularmente complicada. Antes de nos aprofundarmos nessas sutilezas, vamos primeiro obter um GridView listando os fornecedores.
Comece abrindo a RadioButtonField.aspx
página na EnhancedGridView
pasta arrastando um GridView da Caixa de Ferramentas para o Designer. Defina GridView s ID
como Suppliers
e, de sua marca inteligente, escolha criar uma nova fonte de dados. Especificamente, crie um ObjectDataSource chamado SuppliersDataSource
que extraia seus dados do SuppliersBLL
objeto .
Figura 4: Criar um novo objetoDataSource nomeado SuppliersDataSource
(clique para exibir a imagem em tamanho real)
Figura 5: Configurar o ObjectDataSource para usar a SuppliersBLL
classe (clique para exibir a imagem em tamanho real)
Como só queremos listar esses fornecedores nos EUA, escolha o GetSuppliersByCountry(country)
método na lista suspensa na guia SELECT.
Figura 6: Configurar o ObjectDataSource para usar a SuppliersBLL
classe (clique para exibir a imagem em tamanho real)
Na guia UPDATE, selecione a opção (Nenhum) e clique em Avançar.
Figura 7: Configurar o ObjectDataSource para usar a SuppliersBLL
classe (clique para exibir a imagem em tamanho real)
Como o GetSuppliersByCountry(country)
método aceita um parâmetro, o assistente Configurar Fonte de Dados nos solicita a origem desse parâmetro. Para especificar um valor embutido em código (EUA, neste exemplo), deixe a lista suspensa Origem do parâmetro definida como Nenhum e insira o valor padrão na caixa de texto. Clique em Concluir para concluir o assistente.
Figura 8: Usar EUA como o valor padrão para o country
parâmetro (clique para exibir a imagem em tamanho real)
Depois de concluir o assistente, o GridView incluirá um BoundField para cada um dos campos de dados do fornecedor. Remova todos, exceto , CompanyName
City
e Country
BoundFields, e renomeie a CompanyName
propriedade BoundFields HeaderText
como Supplier. Depois de fazer isso, a sintaxe declarativa GridView e ObjectDataSource deve ser semelhante à seguinte.
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
<SelectParameters>
<asp:Parameter DefaultValue="USA" Name="country" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
Para este tutorial, vamos permitir que o usuário exiba os produtos do fornecedor selecionado na mesma página que a lista de fornecedores ou em uma página diferente. Para acomodar isso, adicione dois controles Da Web de botão à página. Defina os ID
s desses dois Botões como ListProducts
e SendToProducts
, com a ideia de que quando ListProducts
for clicado um postback ocorrerá e os produtos do fornecedor selecionado serão listados na mesma página, mas quando SendToProducts
for clicado, o usuário será levado para outra página que lista os produtos.
A Figura 9 mostra o Suppliers
GridView e os dois controles da Web de botão quando exibidos por meio de um navegador.
Figura 9: Os fornecedores dos EUA têm suas informações de nome, cidade e país listadas (clique para exibir a imagem em tamanho real)
Etapa 3: Adicionar uma coluna de botões de opção
Neste ponto, o Suppliers
GridView tem três BoundFields exibindo o nome da empresa, a cidade e o país de cada fornecedor nos EUA. No entanto, ainda falta uma coluna de botões de opção. Infelizmente, o GridView não inclui um RadioButtonField interno, caso contrário, poderíamos apenas adicioná-lo à grade e ser feito. Em vez disso, podemos adicionar um TemplateField e configurá-lo ItemTemplate
para renderizar um botão de opção, resultando em um botão de opção para cada linha gridView.
Inicialmente, podemos supor que a interface do usuário desejada possa ser implementada adicionando um controle Web RadioButton ao ItemTemplate
de um TemplateField. Embora isso realmente adicione um único botão de opção a cada linha do GridView, os botões de opção não podem ser agrupados e, portanto, não são mutuamente exclusivos. Ou seja, um usuário final pode selecionar vários botões de opção simultaneamente no GridView.
Embora o uso de um TemplateField de controles da Web RadioButton não ofereça a funcionalidade necessária, vamos implementar essa abordagem, pois vale a pena examinar por que os botões de opção resultantes não são agrupados. Comece adicionando um TemplateField ao Suppliers GridView, tornando-o o campo mais à esquerda. Em seguida, na marca inteligente GridView, clique no link Editar Modelos e arraste um controle Web RadioButton da Caixa de Ferramentas para o TemplateField s ItemTemplate
(consulte a Figura 10). Defina a propriedade RadioButton como ID
e a GroupName
propriedade como SuppliersGroup
.RowSelector
Figura 10: Adicionar um controle Web RadioButton ao ItemTemplate
(Clique para exibir a imagem em tamanho real)
Depois de fazer essas adições por meio do Designer, a marcação do GridView deve ser semelhante à seguinte:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButton ID="RowSelector" runat="server"
GroupName="SuppliersGroup" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
A propriedade RadioButton s GroupName
é usada para agrupar uma série de botões de opção. Todos os controles RadioButton com o mesmo GroupName
valor são considerados agrupados; somente um botão de opção pode ser selecionado de um grupo por vez. A GroupName
propriedade especifica o valor do atributo do botão de name
opção renderizado. O navegador examina os atributos de botões name
de opção para determinar os agrupamentos de botões de opção.
Com o controle Web RadioButton adicionado ao ItemTemplate
, visite esta página por meio de um navegador e clique nos botões de opção nas linhas da grade. Observe como os botões de opção não são agrupados, tornando possível selecionar todas as linhas, como mostra a Figura 11.
Figura 11: Os botões de opção GridView não estão agrupados (clique para exibir a imagem em tamanho real)
O motivo pelo qual os botões de opção não são agrupados é porque seus atributos renderizados name
são diferentes, apesar de terem a mesma GroupName
configuração de propriedade. Para ver essas diferenças, faça uma Exibição/Fonte do navegador e examine a marcação do botão de opção:
<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector"
name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector"
name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector"
name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector"
name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup"
type="radio" value="RowSelector" />
Observe como os name
atributos e id
não são os valores exatos, conforme especificado no janela Propriedades, mas são precedidos por vários outros ID
valores. Os valores adicionais ID
adicionados à frente dos atributos renderizados id
e name
são os ID
s dos botões de opção pai controla os GridViewRow
s ID
, o GridView s ID
, o Controle de conteúdo s ID
e o Web Form s ID
. Esses ID
s são adicionados para que cada controle da Web renderizado no GridView tenha valores e name
exclusivosid
.
Cada controle renderizado precisa de um diferente name
e id
porque é assim que o navegador identifica exclusivamente cada controle no lado do cliente e como ele identifica para o servidor Web qual ação ou alteração ocorreu no postback. Por exemplo, imagine que queríamos executar algum código do lado do servidor sempre que um estado verificado do RadioButton fosse alterado. Podemos fazer isso definindo a propriedade True
RadioButton como AutoPostBack
e criando um manipulador de eventos para o CheckChanged
evento. No entanto, se os valores renderizados name
e id
para todos os botões de opção forem os mesmos, no postback não foi possível determinar qual RadioButton específico foi clicado.
Resumindo, não é possível criar uma coluna de botões de opção em um GridView usando o controle Web RadioButton. Em vez disso, devemos usar técnicas bastante arcaicas para garantir que a marcação apropriada seja injetada em cada linha gridView.
Observação
Assim como o controle Da Web RadioButton, o controle HTML do botão de opção, quando adicionado a um modelo, incluirá o atributo exclusivo name
, tornando os botões de opção na grade desagrupados. Se você não estiver familiarizado com controles HTML, fique à vontade para ignorar essa observação, pois os controles HTML raramente são usados, especialmente no ASP.NET 2.0. Mas se você estiver interessado em aprender mais, consulte K. Scott Allen entrada de blog Controles web e controles HTML.
Usando um controle literal para injetar marcação de botão de opção
Para agrupar corretamente todos os botões de opção no GridView, precisamos injetar manualmente a marcação de botões de opção no ItemTemplate
. Cada botão de opção precisa do mesmo name
atributo, mas deve ter um atributo exclusivo id
(caso queiramos acessar um botão de opção por meio do script do lado do cliente). Depois que um usuário selecionar um botão de opção e postar de volta a página, o navegador enviará de volta o valor do atributo do botão de value
opção selecionado. Portanto, cada botão de opção precisará de um atributo exclusivo value
. Por fim, no postback, precisamos adicionar o checked
atributo a um botão de opção selecionado; caso contrário, depois que o usuário fizer uma seleção e postar de volta, os botões de opção retornarão ao estado padrão (todos não selecionados).
Há duas abordagens que podem ser tomadas para injetar marcação de baixo nível em um modelo. Uma delas é fazer uma combinação de marcação e chamadas para métodos de formatação definidos na classe code-behind. Essa técnica foi discutida pela primeira vez no tutorial Usando TemplateFields no Controle GridView . Em nosso caso, pode ser algo parecido com:
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
Aqui, GetUniqueRadioButton
e GetRadioButtonValue
seriam métodos definidos na classe code-behind que retornavam os valores de atributo e value
apropriados id
para cada botão de opção. Essa abordagem funciona bem para atribuir os id
atributos e value
, mas fica aquém ao precisar especificar o valor do checked
atributo porque a sintaxe de associação de dados só é executada quando os dados são associados pela primeira vez ao GridView. Portanto, se o GridView tiver o estado de exibição habilitado, os métodos de formatação só serão acionados quando a página for carregada pela primeira vez (ou quando o GridView for explicitamente recuperado para a fonte de dados) e, portanto, a função que define o checked
atributo não será chamada no postback. É um problema bastante sutil e um pouco além do escopo deste artigo, então vou deixá-lo com isso. No entanto, eu encorajo você a tentar usar a abordagem acima e trabalhar até o ponto em que você vai ficar preso. Embora esse exercício não o aproxime de uma versão funcional, ele ajudará a promover uma compreensão mais profunda do GridView e do ciclo de vida de vinculação de dados.
A outra abordagem para injetar marcação personalizada de baixo nível em um modelo e a abordagem que usaremos para este tutorial é adicionar um controle Literal ao modelo. Em seguida, no manipulador de eventos ou RowCreated
RowDataBound
GridView, o controle Literal pode ser acessado programaticamente e sua Text
propriedade definida como a marcação a ser emitida.
Comece removendo o RadioButton do TemplateField s ItemTemplate
, substituindo-o por um controle Literal. Defina o controle literal s ID
como RadioButtonMarkup
.
Figura 12: Adicionar um controle literal ao ItemTemplate
(clique para exibir a imagem em tamanho real)
Em seguida, crie um manipulador de eventos para o evento GridView.RowCreated
O RowCreated
evento é acionado uma vez para cada linha adicionada, independentemente de os dados estarem sendo recuperados ou não para o GridView. Isso significa que, mesmo em um postback quando os dados são recarregados do estado de exibição, o RowCreated
evento ainda é acionado e esse é o motivo pelo qual estamos usando-o em vez de RowDataBound
(que é acionado somente quando os dados são explicitamente associados ao controle da Web de dados).
Nesse manipulador de eventos, só queremos continuar se estivermos lidando com uma linha de dados. Para cada linha de dados, queremos referenciar programaticamente o RadioButtonMarkup
controle Literal e definir sua Text
propriedade como a marcação a ser emitida. Como mostra o código a seguir, a marcação emitida cria um botão de opção cujo name
atributo é definido SuppliersGroup
como , cujo id
atributo é definido RowSelectorX
como , em que X é o índice da linha GridView e cujo value
atributo é definido como o índice da linha GridView.
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex)
End If
End Sub
Quando uma linha GridView é selecionada e ocorre um postback, estamos interessados no SupplierID
do fornecedor selecionado. Portanto, pode-se pensar que o valor de cada botão de opção deve ser o real SupplierID
(em vez do índice da linha GridView). Embora isso possa funcionar em determinadas circunstâncias, seria um risco de segurança aceitar e processar cegamente um SupplierID
. Nosso GridView, por exemplo, lista apenas os fornecedores nos EUA. No entanto, se o SupplierID
for passado diretamente do botão de opção, o que impedirá um usuário travesso de manipular o SupplierID
valor enviado de volta no postback? Usando o índice de linha como e value
, em seguida, obtendo o SupplierID
no postback da DataKeys
coleção, podemos garantir que o usuário esteja usando apenas um dos SupplierID
valores associados a uma das linhas GridView.
Depois de adicionar esse código do manipulador de eventos, reserve um minuto para testar a página em um navegador. Primeiro, observe que apenas um botão de opção na grade pode ser selecionado por vez. No entanto, ao selecionar um botão de opção e clicar em um dos botões, um postback ocorre e os botões de opção reverter ao estado inicial (ou seja, no postback, o botão de opção selecionado não está mais selecionado). Para corrigir isso, precisamos aumentar o RowCreated
manipulador de eventos para que ele inspecione o índice de botão de opção selecionado enviado do postback e adicione o checked="checked"
atributo à marcação emitida das correspondências de índice de linha.
Quando ocorre um postback, o navegador envia de volta o name
e value
o do botão de opção selecionado. O valor pode ser recuperado programaticamente usando Request.Form("name")
. A Request.Form
propriedade fornece um NameValueCollection
que representa as variáveis de formulário. As variáveis de formulário são os nomes e valores dos campos de formulário na página da Web e são enviadas de volta pelo navegador da Web sempre que um postback ocorre. Como o atributo renderizado name
dos botões de opção no GridView é SuppliersGroup
, quando a página da Web é postada de volta, o navegador enviará SuppliersGroup=valueOfSelectedRadioButton
de volta para o servidor Web (juntamente com os outros campos de formulário). Essas informações podem ser acessadas da Request.Form
propriedade usando: Request.Form("SuppliersGroup")
.
Como precisaremos determinar o índice do botão de opção selecionado não apenas no RowCreated
manipulador de eventos, mas nos Click
manipuladores de eventos para os controles da Web button, vamos adicionar uma SuppliersSelectedIndex
propriedade à classe code-behind que retorna -1
se nenhum botão de opção foi selecionado e o índice selecionado se um dos botões de opção estiver selecionado.
Private ReadOnly Property SuppliersSelectedIndex() As Integer
Get
If String.IsNullOrEmpty(Request.Form("SuppliersGroup")) Then
Return -1
Else
Return Convert.ToInt32(Request.Form("SuppliersGroup"))
End If
End Get
End Property
Com essa propriedade adicionada, sabemos adicionar a checked="checked"
marcação no RowCreated
manipulador de eventos quando SuppliersSelectedIndex
for igual e.Row.RowIndex
a . Atualize o manipulador de eventos para incluir essa lógica:
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}"", e.Row.RowIndex)
' See if we need to add the "checked" attribute
If SuppliersSelectedIndex = e.Row.RowIndex Then
output.Text &= " checked="checked""
End If
' Add the closing tag
output.Text &= " />"
End If
End Sub
Com essa alteração, o botão de opção selecionado permanece selecionado após um postback. Agora que temos a capacidade de especificar qual botão de opção está selecionado, podemos alterar o comportamento para que, quando a página foi visitada pela primeira vez, o primeiro botão de opção da linha GridView tenha sido selecionado (em vez de não ter botões de opção selecionados por padrão, que é o comportamento atual). Para que o primeiro botão de opção seja selecionado por padrão, basta alterar a If SuppliersSelectedIndex = e.Row.RowIndex Then
instrução para o seguinte: If SuppliersSelectedIndex = e.Row.RowIndex OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then
.
Neste ponto, adicionamos uma coluna de botões de opção agrupados ao GridView que permite que uma única linha GridView seja selecionada e lembrada entre postbacks. Nossas próximas etapas são exibir os produtos fornecidos pelo fornecedor selecionado. Na Etapa 4, veremos como redirecionar o usuário para outra página, enviando ao longo do selecionado SupplierID
. Na Etapa 5, veremos como exibir os produtos do fornecedor selecionado em um GridView na mesma página.
Observação
Em vez de usar um TemplateField (o foco desta longa Etapa 3), poderíamos criar uma classe personalizada DataControlField
que renderiza a interface do usuário e a funcionalidade apropriadas. A DataControlField
classe é a classe base da qual os campos BoundField, CheckBoxField, TemplateField e outros campos internos GridView e DetailsView derivam. Criar uma classe personalizada DataControlField
significaria que a coluna de botões de opção poderia ser adicionada apenas usando sintaxe declarativa e também facilitaria significativamente a replicação da funcionalidade em outras páginas da Web e em outros aplicativos Web.
Se você já criou controles personalizados e compilados em ASP.NET, no entanto, você sabe que isso requer uma boa quantidade de trabalho e carrega consigo uma série de sutilezas e casos de borda que devem ser cuidadosamente tratados. Portanto, vamos renunciar à implementação de uma coluna de botões de opção como uma classe personalizada DataControlField
por enquanto e ficar com a opção TemplateField. Talvez tenhamos a chance de explorar a criação, o uso e a implantação de classes personalizadas DataControlField
em um tutorial futuro!
Etapa 4: Exibindo os produtos do fornecedor selecionado em uma página separada
Depois que o usuário tiver selecionado uma linha GridView, precisaremos mostrar os produtos do fornecedor selecionado. Em algumas circunstâncias, talvez queiramos exibir esses produtos em uma página separada, em outras, talvez prefira fazê-lo na mesma página. Primeiro, vamos examinar como exibir os produtos em uma página separada; Na Etapa 5, examinaremos a adição de um GridView para RadioButtonField.aspx
exibir os produtos do fornecedor selecionado.
Atualmente, há dois controles Da Web de botão na página ListProducts
e SendToProducts
. Quando o SendToProducts
Botão é clicado, queremos enviar o usuário para ~/Filtering/ProductsForSupplierDetails.aspx
. Esta página foi criada no tutorial Filtragem Mestre/Detalhes em Duas Páginas e exibe os produtos para o fornecedor cujo SupplierID
é passado pelo campo querystring chamado SupplierID
.
Para fornecer essa funcionalidade, crie um manipulador de eventos para o SendToProducts
evento Do Click
botão. Na Etapa 3, adicionamos a SuppliersSelectedIndex
propriedade , que retorna o índice da linha cujo botão de opção está selecionado. O correspondente SupplierID
pode ser recuperado da coleção GridView e DataKeys
, em seguida, o usuário pode ser enviado para ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
usando Response.Redirect("url")
.
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End Sub
Esse código funciona maravilhosamente, desde que um dos botões de opção seja selecionado no GridView. Se, inicialmente, o GridView não tiver nenhum botão de opção selecionado e o usuário clicar no botão, SuppliersSelectedIndex
será , o SendToProducts
que fará com que uma exceção seja gerada, pois -1
está fora do intervalo de índice da DataKeys
coleção-1
. No entanto, isso não é uma preocupação se você decidiu atualizar o RowCreated
manipulador de eventos conforme discutido na Etapa 3 para que o primeiro botão de opção no GridView seja selecionado inicialmente.
Para acomodar um SuppliersSelectedIndex
valor de -1
, adicione um controle Web Label à página acima do GridView. Defina sua ID
propriedade ChooseSupplierMsg
como , sua CssClass
propriedade como Warning
, suas EnableViewState
propriedades False
e Visible
como e sua Text
propriedade como Por favor, escolha um fornecedor na grade. A classe Warning
CSS exibe texto em uma fonte vermelha, itálica, negrito, grande e é definida em Styles.css
. Ao definir as EnableViewState
propriedades e Visible
como False
, o Rótulo não é renderizado, exceto apenas para os postbacks em que a propriedade s do Visible
controle é definida True
programaticamente como .
Figura 13: Adicionar um controle Web de rótulo acima do GridView (clique para exibir a imagem em tamanho real)
Em seguida, aumente o Click
manipulador de eventos para exibir o ChooseSupplierMsg
Rótulo se SuppliersSelectedIndex
for menor que zero e redirecione o usuário para ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
o contrário.
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
Else
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End If
End Sub
Visite a página em um navegador e clique no SendToProducts
botão antes de selecionar um fornecedor no GridView. Como mostra a Figura 14, isso exibe o ChooseSupplierMsg
rótulo. Em seguida, selecione um fornecedor e clique no SendToProducts
botão. Isso levará você a uma página que lista os produtos fornecidos pelo fornecedor selecionado. A Figura 15 mostra a ProductsForSupplierDetails.aspx
página quando o fornecedor das Cervejarias Bigfoot foi selecionado.
Figura 14: o ChooseSupplierMsg
rótulo será exibido se nenhum fornecedor estiver selecionado (clique para exibir a imagem em tamanho real)
Figura 15: Os produtos do fornecedor selecionado são exibidos em ProductsForSupplierDetails.aspx
(Clique para exibir a imagem em tamanho real)
Etapa 5: Exibindo os produtos do fornecedor selecionado na mesma página
Na Etapa 4, vimos como enviar o usuário para outra página da Web para exibir os produtos do fornecedor selecionado. Como alternativa, os produtos do fornecedor selecionado podem ser exibidos na mesma página. Para ilustrar isso, adicionaremos outro GridView para RadioButtonField.aspx
exibir os produtos do fornecedor selecionado.
Como só queremos que esse GridView de produtos seja exibido depois que um fornecedor tiver sido selecionado, adicione um controle Web painel abaixo do GridView, definindo-o Suppliers
ID
como ProductsBySupplierPanel
e sua Visible
propriedade como False
. No Painel, adicione o texto Produtos para o Fornecedor Selecionado, seguido por um GridView chamado ProductsBySupplier
. Na marca inteligente GridView, escolha associá-la a um novo ObjectDataSource chamado ProductsBySupplierDataSource
.
Figura 16: Associar o ProductsBySupplier
GridView a um Novo ObjetoDataSource (Clique para exibir a imagem em tamanho real)
Em seguida, configure o ObjectDataSource para usar a ProductsBLL
classe . Como só queremos recuperar esses produtos fornecidos pelo fornecedor selecionado, especifique que ObjectDataSource deve invocar o GetProductsBySupplierID(supplierID)
método para recuperar seus dados. Selecione (Nenhum) nas listas suspensas nas guias UPDATE, INSERT e DELETE.
Figura 17: configurar o ObjectDataSource para usar o GetProductsBySupplierID(supplierID)
método (clique para exibir a imagem em tamanho real)
Figura 18: defina o Drop-Down Listas como (Nenhum) nas guias UPDATE, INSERT e DELETE (Clique para exibir a imagem em tamanho real)
Depois de configurar as guias SELECT, UPDATE, INSERT e DELETE, clique em Avançar. Como o GetProductsBySupplierID(supplierID)
método espera um parâmetro de entrada, o assistente Criar Fonte de Dados solicita que especifiquemos a origem do valor do parâmetro.
Temos algumas opções aqui para especificar a origem do valor do parâmetro. Poderíamos usar o objeto Parameter padrão e atribuir programaticamente o valor da SuppliersSelectedIndex
propriedade à propriedade Parameter no DefaultValue
manipulador de eventos ObjectDataSource Selecting
. Consulte o tutorial Definindo programaticamente os valores de parâmetro do ObjectDataSource para um atualizador sobre como atribuir valores programaticamente aos parâmetros objectDataSource.
Como alternativa, podemos usar um ControlParameter e consultar a Suppliers
propriedade GridView (SelectedValue
consulte a Figura 19). A propriedade GridView SelectedValue
retorna o DataKey
valor correspondente à SelectedIndex
propriedade . Para que essa opção funcione, precisamos definir programaticamente a propriedade GridView como SelectedIndex
a linha selecionada quando o ListProducts
botão for clicado. Como um benefício adicional, definindo o SelectedIndex
, o registro selecionado assumirá o SelectedRowStyle
definido no DataWebControls
Tema (uma tela de fundo amarela).
Figura 19: use um ControlParameter para especificar SelectedValue do GridView como a origem do parâmetro (clique para exibir a imagem em tamanho real)
Ao concluir o assistente, o Visual Studio adicionará automaticamente campos para os campos de dados do produto. Remova todos, exceto , ProductName
CategoryName
e UnitPrice
BoundFields, e altere as HeaderText
propriedades para Product, Category e Price. Configure o UnitPrice
BoundField para que seu valor seja formatado como uma moeda. Depois de fazer essas alterações, a marcação declarativa de Panel, GridView e ObjectDataSource deve ser semelhante à seguinte:
<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
<h3>
Products for the Selected Supplier</h3>
<p>
<asp:GridView ID="ProductsBySupplier" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
<SelectParameters>
<asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</p>
</asp:Panel>
Para concluir este exercício, precisamos definir a propriedade GridView SelectedIndex
como e SelectedSuppliersIndex
a ProductsBySupplierPanel
propriedade Do Visible
Painel como True
quando o ListProducts
botão é clicado. Para fazer isso, crie um manipulador de eventos para o ListProducts
evento button Web control e Click
adicione o seguinte código:
Protected Sub ListProducts_Click(sender As Object, e As EventArgs) _
Handles ListProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
ProductsBySupplierPanel.Visible = False
Else
' Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex
' Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = True
End If
End Sub
Se um fornecedor não tiver sido selecionado no GridView, o ChooseSupplierMsg
Rótulo será exibido e o ProductsBySupplierPanel
Painel ficará oculto. Caso contrário, se um fornecedor tiver sido selecionado, o ProductsBySupplierPanel
será exibido e a propriedade GridView será SelectedIndex
atualizada.
A Figura 20 mostra os resultados depois que o fornecedor das Cervejarias Bigfoot foi selecionado e o botão Mostrar Produtos na Página foi clicado.
Figura 20: Os produtos fornecidos pelas cervejarias Bigfoot estão listados na mesma página (clique para exibir a imagem em tamanho real)
Resumo
Conforme discutido no mestre/detalhe Usando um Selectable Master GridView com um tutorial Details DetailView , os registros podem ser selecionados em um GridView usando um CommandField cuja ShowSelectButton
propriedade está definida como True
. Mas o CommandField exibe seus botões como botões de push regulares, links ou imagens. Uma interface de usuário de seleção de linha alternativa é fornecer um botão de opção ou uma caixa de seleção em cada linha gridView. Neste tutorial, examinamos como adicionar uma coluna de botões de opção.
Infelizmente, adicionar uma coluna de botões de opção não é tão simples ou simples quanto se poderia esperar. Não há nenhum RadioButtonField interno que possa ser adicionado ao clicar em um botão e usar o controle Web RadioButton em um TemplateField apresenta seu próprio conjunto de problemas. No final, para fornecer essa interface, precisamos criar uma classe personalizada DataControlField
ou recorrer a injetar o HTML apropriado em um TemplateField durante o RowCreated
evento.
Tendo explorado como adicionar uma coluna de botões de opção, vamos voltar nossa atenção para adicionar uma coluna de caixas de seleção. Com uma coluna de caixas de seleção, um usuário pode selecionar uma ou mais linhas gridView e, em seguida, executar alguma operação em todas as linhas selecionadas (como selecionar um conjunto de emails de um cliente de email baseado na Web e, em seguida, optar por excluir todos os emails selecionados). No próximo tutorial, veremos como adicionar essa coluna.
Programação feliz!
Sobre o autor
Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.
Agradecimentos Especiais
Esta série de tutoriais foi revisada por muitos revisores úteis. O revisor principal deste tutorial foi David Suru. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, solte-me uma linha em mitchell@4GuysFromRolla.com.