Agregar una columna GridView de botones de radio (C#)

por Scott Mitchell

Descarga de la aplicación de ejemplo o descarga de PDF

En este tutorial se examina cómo agregar una columna de botones de radio a un control GridView para proporcionar al usuario una forma más intuitiva de seleccionar una sola fila de GridView.

Introducción

El control GridView ofrece una gran cantidad de funcionalidad integrada. Incluye varios campos diferentes para mostrar texto, imágenes, hipervínculos y botones. Admite plantillas para una personalización adicional. Con unos pocos clics del mouse, es posible crear un control GridView en el que se pueda seleccionar cada fila a través de un botón, o bien habilitar la edición o la eliminación de capacidades. A pesar de la gran cantidad de características proporcionadas, a menudo habrá situaciones en las que será necesario agregar características adicionales no compatibles. En este tutorial y en los dos siguientes examinaremos cómo mejorar la funcionalidad de GridView para incluir características adicionales.

Este tutorial y el siguiente se centran en mejorar el proceso de selección de filas. Tal y como se ha examinado en el maestro y detalles mediante un GridView maestro seleccionable con un DetailView de detalles, podemos agregar un CommandField a GridView que incluya un botón seleccionar. Al hacer clic en él, aparece un postback y la propiedad GridView s SelectedIndex se actualiza en el índice de la fila cuyo botón seleccionar se hizo clic. En el tutorial maestro y detalles mediante un control GridView de la página maestra seleccionable con un DetailView de detalles , vimos cómo usar esta característica para mostrar los detalles de la fila de GridView seleccionada.

Aunque el botón seleccionar funciona en muchas situaciones, puede que no funcione también para otros usuarios. En lugar de usar un botón, se suelen usar otros dos elementos de la interfaz de usuario para la selección: el botón de radio y la casilla. Podemos aumentar el control GridView para que en lugar de un botón seleccionar, cada fila contenga un botón de radio o una casilla. En escenarios en los que el usuario solo puede seleccionar uno de los registros de GridView, es posible que se prefiera el botón de radio para el botón seleccionar. En situaciones en las que el usuario puede seleccionar potencialmente varios registros como en una aplicación de correo electrónico basada en Web, donde un usuario podría querer seleccionar varios mensajes para eliminar la casilla ofrece una funcionalidad que no está disponible en el botón seleccionar o el botón de radio interfaces de usuario.

En este tutorial se examina cómo agregar una columna de botones de radio a GridView. El tutorial de continuación explora el uso de las casillas.

Paso 1: crear la mejora de las páginas web de GridView

Antes de empezar a mejorar GridView para incluir una columna de botones de radio, vamos a crear las páginas de ASP.NET en nuestro proyecto de sitio web que necesitamos para este tutorial y los dos siguientes. Comience agregando una nueva carpeta denominada EnhancedGridView. A continuación, agregue las siguientes páginas de ASP.NET a esa carpeta, asegurándose de asociar cada página a la página maestra de Site.master:

  • Default.aspx
  • RadioButtonField.aspx
  • CheckBoxField.aspx
  • InsertThroughFooter.aspx

Agregue las páginas ASP.NET para los tutoriales relacionados con SqlDataSource

Figura 1: agregar las páginas ASP.net para los tutoriales relacionados con SqlDataSource

Al igual que en las otras carpetas, Default.aspx en la carpeta EnhancedGridView mostrará los tutoriales en su sección. Recuerde que el control de usuario SectionLevelTutorialListing.ascx proporciona esta funcionalidad. Por lo tanto, agregue este control de usuario a Default.aspx arrastrándolo desde el Explorador de soluciones hasta la página s Vista de diseño.

agregar el control de usuario SectionLevelTutorialListing. ascx a default. aspx

Figura 2: agregar el control de usuario SectionLevelTutorialListing.ascx a Default.aspx (haga clic para ver la imagen de tamaño completo)

Por último, agregue estas cuatro páginas como entradas al archivo Web.sitemap. En concreto, agregue el siguiente marcado después de usar el control SqlDataSource <siteMapNode>:

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

Después de actualizar Web.sitemap, dedique un momento a ver el sitio web de tutoriales a través de un explorador. El menú de la izquierda incluye ahora los elementos para los tutoriales de edición, inserción y eliminación.

El mapa del sitio ahora incluye entradas para mejorar los tutoriales de GridView

Figura 3: ahora, el mapa del sitio incluye entradas para mejorar los tutoriales de GridView.

Paso 2: mostrar los proveedores en un control GridView

En este tutorial, vamos a crear un GridView que enumera los proveedores de EE. UU., con cada fila de GridView que proporciona un botón de radio. Después de seleccionar un proveedor mediante el botón de radio, el usuario puede ver los productos de proveedores haciendo clic en un botón. Aunque esta tarea puede parecer trivial, hay una serie de matices que lo hacen especialmente complicado. Antes de profundizar en estas sutilezas, vamos a obtener primero un control GridView que muestre los proveedores.

Para empezar, abra la página de RadioButtonField.aspx de la carpeta EnhancedGridView arrastrando un control GridView desde el cuadro de herramientas hasta el diseñador. Establezca el ID de GridView en Suppliers y, desde su etiqueta inteligente, elija crear un nuevo origen de datos. En concreto, cree un ObjectDataSource denominado SuppliersDataSource que extraiga sus datos del objeto SuppliersBLL.

crear un nuevo ObjectDataSource denominado SuppliersDataSource

Figura 4: creación de un nuevo ObjectDataSource denominado SuppliersDataSource (haga clic para ver la imagen de tamaño completo)

configurar ObjectDataSource para usar la clase SuppliersBLL

Figura 5: configuración de ObjectDataSource para usar la clase SuppliersBLL (haga clic para ver la imagen de tamaño completo)

Puesto que solo queremos enumerar esos proveedores en Estados Unidos, elija el método de GetSuppliersByCountry(country) en la lista desplegable de la pestaña seleccionar.

configurar ObjectDataSource para usar la clase SuppliersBLL

Figura 6: configuración de ObjectDataSource para usar la clase SuppliersBLL (haga clic para ver la imagen de tamaño completo)

En la pestaña actualizar, seleccione la opción (ninguno) y haga clic en siguiente.

configurar ObjectDataSource para usar la clase SuppliersBLL

Figura 7: configuración de ObjectDataSource para usar la clase SuppliersBLL (haga clic para ver la imagen de tamaño completo)

Dado que el método GetSuppliersByCountry(country) acepta un parámetro, el Asistente para configurar el origen de datos nos solicita el origen de ese parámetro. Para especificar un valor codificado de forma rígida (EE. UU., en este ejemplo), deje la lista desplegable origen de parámetro establecida en ninguno y escriba el valor predeterminado en el cuadro de texto. Haga clic en Finalizar para completar el asistente.

usar USA como valor predeterminado para el parámetro Country

Figura 8: Use usa como valor predeterminado para el parámetro country (haga clic para ver la imagen de tamaño completo)

Después de completar el asistente, GridView incluirá una BoundField para cada uno de los campos de datos de proveedor. Quite todos los CompanyName, Cityy Country BoundFields, y cambie el nombre de la propiedad CompanyName BoundFields HeaderText a supplier. Después de hacerlo, la sintaxis declarativa de GridView y ObjectDataSource debe ser similar a la siguiente.

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

En este tutorial, permitiría al usuario ver los productos de proveedores seleccionados en la misma página que la lista de proveedores o en otra página. Para ello, agregue dos controles Web de botón a la página. Configure los ID s de estos dos botones en ListProducts y SendToProducts, con la idea de que, cuando se hace clic en ListProducts, se producirá un postback y los productos de los proveedores seleccionados se mostrarán en la misma página, pero cuando se haga clic en SendToProducts, el usuario se recogerá en otra página que muestre los productos.

En la ilustración 9 se muestra la Suppliers GridView y los dos controles Web de botón cuando se ven a través de un explorador.

esos proveedores de EE. UU. tienen su nombre, ciudad e información de país en la lista

Figura 9: estos proveedores de EE. UU. tienen su nombre, ciudad e información de país (haga clic para ver la imagen a tamaño completo)

Paso 3: agregar una columna de botones de radio

En este momento, el Suppliers GridView tiene tres BoundFields que muestran el nombre de la empresa, la ciudad y el país de cada proveedor de EE. UU. Sin embargo, todavía falta una columna de botones de radio. Desafortunadamente, el control GridView no incluye un RadioButtonField integrado; de lo contrario, podríamos agregarlo a la cuadrícula y hacerlo. En su lugar, podemos agregar un TemplateField y configurar su ItemTemplate para representar un botón de radio, lo que da como resultado un botón de radio para cada fila de GridView.

En principio, podríamos suponer que la interfaz de usuario deseada puede implementarse agregando un control Web RadioButton al ItemTemplate de un TemplateField. Aunque esto agregará un solo botón de radio a cada fila de GridView, los botones de radio no se pueden agrupar y, por lo tanto, no son mutuamente excluyentes. Es decir, un usuario final puede seleccionar varios botones de radio simultáneamente desde GridView.

Aunque el uso de un control TemplateField de controles Web RadioButton no ofrece la funcionalidad que necesitamos, vamos a implementar este enfoque, ya que merece la pena examinar por qué los botones de radio resultantes no están agrupados. Empiece agregando un TemplateField al GridView proveedores, convirtiéndolo en el campo de la izquierda. Después, en la etiqueta inteligente de GridView s, haga clic en el vínculo editar plantillas y arrastre un control Web RadioButton desde el cuadro de herramientas hasta el ItemTemplate TemplateField s (consulte la figura 10). Establezca la propiedad RadioButton s ID en RowSelector y la propiedad GroupName en SuppliersGroup.

agregar un control Web RadioButton al ItemTemplate

Figura 10: agregar un control Web RadioButton al ItemTemplate (haga clic para ver la imagen de tamaño completo)

Después de hacer estas adiciones a través del diseñador, el marcado de GridView s debe ser similar al siguiente:

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

La propiedad RadioButton s GroupName es lo que se utiliza para agrupar una serie de botones de radio. Todos los controles RadioButton con el mismo valor GroupName se consideran agrupados; solo se puede seleccionar un botón de radio de un grupo a la vez. La propiedad GroupName especifica el valor para el atributo de name de botón de radio representado. El explorador examina los botones de radio name los atributos para determinar las agrupaciones de botones de radio.

Con el control Web RadioButton agregado al ItemTemplate, visite esta página a través de un explorador y haga clic en los botones de radio de las filas de la cuadrícula. Observe que los botones de radio no están agrupados, lo que permite seleccionar todas las filas, tal y como se muestra en la figura 11.

los botones de radio de GridView no están agrupados

Figura 11: los botones de radio de GridView no están agrupados (haga clic para ver la imagen de tamaño completo)

El motivo por el que los botones de radio no están agrupados se debe a que sus atributos de name representados son diferentes, a pesar de tener el mismo valor de propiedad GroupName. Para ver estas diferencias, haga una vista o código fuente desde el explorador y examine el marcado del botón de radio:

<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 cómo los atributos name y id no son los valores exactos tal y como se especifican en el ventana Propiedades, pero se anteponen a otros valores de ID. Los valores de ID adicionales agregados al principio de los atributos id y name que se representan son los ID s de los botones de radio que controla los GridViewRow ID s, GridView s ID, el control de contenido IDy el formulario Web Forms ID. Estos ID s se agregan de modo que cada control Web representado en GridView tenga un id y valores name únicos.

Cada control representado necesita un name y id diferentes, ya que es el modo en que el explorador identifica de forma única cada control en el lado cliente y cómo identifica al servidor Web qué acción o cambio se ha producido en el PostBack. Por ejemplo, Imagine que desea ejecutar código de servidor cada vez que se cambia un estado RadioButton s Checked. Podríamos lograr esto estableciendo la propiedad RadioButton s AutoPostBack en true y creando un controlador de eventos para el evento CheckChanged. Sin embargo, si los valores de name y id representados para todos los botones de radio eran los mismos, en el PostBack no se pudo determinar en qué RadioButton se hizo clic.

Lo breve es que no se puede crear una columna de botones de radio en un control GridView mediante el control Web RadioButton. En su lugar, se deben usar técnicas de arcaico para asegurarse de que el marcado adecuado se inserta en cada fila de GridView.

Note

Al igual que el control Web RadioButton, el control HTML del botón de radio, cuando se agrega a una plantilla, incluirá el atributo name único, de modo que los botones de radio de la cuadrícula no estén agrupados. Si no está familiarizado con los controles HTML, no dude en omitir esta nota, ya que los controles HTML rara vez se usan, especialmente en ASP.NET 2,0. Pero si está interesado en obtener más información, consulte la entrada del blog de Scott Allen s y controles html.

Usar un control literal para insertar el marcado de botón de radio

Para agrupar correctamente todos los botones de radio dentro de GridView, es necesario insertar manualmente el marcado de los botones de radio en el ItemTemplate. Cada botón de radio necesita el mismo name atributo, pero debe tener un atributo de id único (en caso de que desee tener acceso a un botón de radio a través de un script del lado cliente). Después de que un usuario selecciona un botón de radio y vuelve a enviar la página, el explorador devolverá el valor del botón de radio seleccionado s value atributo. Por lo tanto, cada botón de radio necesitará un atributo de value único. Por último, en el postback, es necesario asegurarse de agregar el atributo checked al botón de radio seleccionado; de lo contrario, una vez que el usuario realiza una selección y devuelve datos, los botones de radio volverán a su estado predeterminado (todos no seleccionados).

Existen dos enfoques que se pueden realizar para insertar marcado de bajo nivel en una plantilla. Uno consiste en combinar el marcado y las llamadas a los métodos de formato definidos en la clase de código subyacente. Esta técnica se analizó en primer lugar en el tutorial uso de TemplateFields en el control GridView . En nuestro caso, podría ser similar a lo siguiente:

<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>' 
    name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />

En este caso, GetUniqueRadioButton y GetRadioButtonValue serían métodos definidos en la clase de código subyacente que devolvieron los valores de atributo id y value adecuados para cada botón de radio. Este enfoque funciona bien para asignar los atributos id y value, pero es breve cuando se necesita especificar el valor del atributo checked porque la sintaxis de DataBinding solo se ejecuta cuando se enlazan los datos por primera vez a GridView. Por consiguiente, si GridView tiene el estado de vista habilitado, los métodos de formato solo se activarán cuando se cargue la página por primera vez (o cuando GridView se reenlace explícitamente al origen de datos) y, por lo tanto, no se llamará a la función que establece el atributo checked en el PostBack. Es un problema bastante sutil y un poco más allá del ámbito de este artículo, por lo que lo dejaré en este caso. Sin embargo, le recomendamos que pruebe a usar el enfoque anterior y que trabaje con el punto en el que se bloqueará. Aunque este ejercicio no le llevará más cerca de una versión de trabajo, le ayudará a fomentar una comprensión más profunda de GridView y el ciclo de vida de los enlaces de la información.

El otro enfoque para insertar el marcado de bajo nivel personalizado en una plantilla y el enfoque que vamos a usar para este tutorial es agregar un control literal a la plantilla. A continuación, en el RowCreated de GridView o en el controlador de eventos RowDataBound, se puede tener acceso mediante programación al control literal y su propiedad Text establecida en el marcado que se va a emitir.

Comience quitando el RadioButton del ItemTemplateTemplateField s, reemplazándolo por un control literal. Establezca el ID de control literal en RadioButtonMarkup.

agregar un control literal al ItemTemplate

Figura 12: agregar un control Literal al ItemTemplate (haga clic para ver la imagen de tamaño completo)

A continuación, cree un controlador de eventos para el evento GridView s RowCreated. El evento RowCreated se activa una vez por cada fila agregada, tanto si los datos se están reenlazando a GridView como si no. Esto significa que, incluso en un postback cuando los datos se recargan desde el estado de vista, el evento de RowCreated se sigue desencadenando y este es el motivo por el que lo usamos en lugar de RowDataBound (que solo se activa cuando los datos están enlazados explícitamente al control Web de datos).

En este controlador de eventos, solo queremos continuar si se refiere a una fila de datos. Para cada fila de datos, se desea hacer referencia mediante programación al control literal RadioButtonMarkup y establecer su propiedad Text en el marcado que se va a emitir. Como se muestra en el código siguiente, el marcado emitido crea un botón de radio cuyo atributo name está establecido en SuppliersGroup, cuyo atributo id está establecido en RowSelectorX, donde X es el índice de la fila de GridView y cuyo atributo value está establecido en el índice de la fila de GridView.

protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Grab a reference to the Literal control
        Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
        // 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);
    }
}

Cuando se selecciona una fila de GridView y se produce un postback, estamos interesados en el SupplierID del proveedor seleccionado. Por lo tanto, se podría pensar que el valor de cada botón de radio debe ser el SupplierID real (en lugar del índice de la fila de GridView). Aunque esto puede funcionar en determinadas circunstancias, sería un riesgo de seguridad para aceptar y procesar una SupplierID. Por ejemplo, nuestro GridView muestra solo los proveedores de EE. UU. Sin embargo, si el SupplierID se pasa directamente desde el botón de radio, ¿qué se debe hacer para que un usuario de este manipule el SupplierID valor que se devuelve en el PostBack? Utilizando el índice de fila como valuey, a continuación, obteniendo el SupplierID en el PostBack de la colección de DataKeys, podemos asegurarnos de que el usuario solo usa uno de los valores de SupplierID asociados a una de las filas de GridView.

Después de agregar este código de controlador de eventos, dedique un minuto a probar la página en un explorador. En primer lugar, tenga en cuenta que solo se puede seleccionar un botón de radio de la cuadrícula a la vez. Sin embargo, al seleccionar un botón de radio y hacer clic en uno de los botones, se produce un postback y los botones de radio se revierten a su estado inicial (es decir, en el postback, el botón de radio seleccionado ya no está seleccionado). Para corregir esto, es necesario aumentar el controlador de eventos RowCreated para que inspeccione el índice de botón de radio seleccionado enviado desde el PostBack y agregue el atributo checked="checked" al marcado emitido de las coincidencias de índice de fila.

Cuando se produce un postback, el explorador devuelve el name y value del botón de radio seleccionado. El valor se puede recuperar mediante programación mediante Request.Form["name"]. La propiedadRequest.Form proporciona un NameValueCollection que representa las variables de formulario. Las variables de formulario son los nombres y los valores de los campos de formulario de la página web, y el explorador web los devuelve cada vez que se produce un postback. Dado que el atributo rendered name de los botones de radio de GridView es SuppliersGroup, cuando se devuelve la página web, el explorador enviará SuppliersGroup=valueOfSelectedRadioButton de vuelta al servidor Web (junto con los demás campos de formulario). A continuación, se puede tener acceso a esta información desde la propiedad Request.Form mediante: Request.Form["SuppliersGroup"].

Dado que es necesario determinar el índice del botón de radio seleccionado no solo en el controlador de eventos RowCreated, pero en los controladores de eventos de Click para los controles Web de botón, permite agregar una propiedad SuppliersSelectedIndex a la clase de código subyacente que devuelve -1 si no se ha seleccionado ningún botón de radio y el índice seleccionado si se ha seleccionado uno de los botones de radio.

private int SuppliersSelectedIndex
{
    get
    {
        if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
            return -1;
        else
            return Convert.ToInt32(Request.Form["SuppliersGroup"]);
    }
}

Con esta propiedad agregada, sabemos agregar el marcado checked="checked" en el controlador de eventos RowCreated cuando SuppliersSelectedIndex es igual a e.Row.RowIndex. Actualice el controlador de eventos para incluir esta lógica:

protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Grab a reference to the Literal control
        Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
        // 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)
            output.Text += @" checked="checked"";
        // Add the closing tag
        output.Text += " />";
    }
}

Con este cambio, el botón de radio seleccionado permanece seleccionado después de un postback. Ahora que tenemos la capacidad de especificar qué botón de radio está seleccionado, podríamos cambiar el comportamiento de modo que, cuando se Visitó la página por primera vez, se seleccione el primer botón de radio de la fila de GridView (en lugar de no tener botones de radio seleccionados de forma predeterminada, que es el actual. comportamiento). Para que el primer botón de radio esté seleccionado de forma predeterminada, simplemente cambie la instrucción if (SuppliersSelectedIndex == e.Row.RowIndex) a lo siguiente: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0)).

En este punto se ha agregado una columna de botones de radio agrupados a GridView que permite seleccionar una sola fila de GridView y recordarla en los postbacks. Los pasos siguientes son para mostrar los productos proporcionados por el proveedor seleccionado. En el paso 4, veremos cómo redirigir al usuario a otra página, enviando a lo largo de la SupplierIDseleccionada. En el paso 5, veremos cómo mostrar los productos de proveedores seleccionados en un control GridView en la misma página.

Note

En lugar de usar TemplateField (el enfoque de este largo paso 3), podríamos crear una clase de DataControlField personalizada que represente la interfaz de usuario y la funcionalidad adecuadas. La claseDataControlField es la clase base de la que derivan BoundField, CheckBoxField, TemplateField y otros campos de GridView y DetailsView integrados. La creación de una clase de DataControlField personalizada significa que la columna de botones de radio se podría agregar simplemente mediante la sintaxis declarativa, y también simplificaría considerablemente la replicación de la funcionalidad en otras páginas web y otras aplicaciones Web.

Sin embargo, si ya ha creado controles personalizados y compilados en ASP.NET, sabe que esto requiere una cantidad justa de tareas y que lleva con él un host de matices y casos de borde que deben controlarse cuidadosamente. Por lo tanto, se renunciará a la implementación de una columna de botones de radio como una clase de DataControlField personalizada por ahora y se adhiere a la opción TemplateField. Quizás tengamos la oportunidad de explorar la creación, el uso y la implementación de clases de DataControlField personalizadas en un tutorial futuro.

Paso 4: mostrar los productos de proveedores seleccionados en una página independiente

Una vez que el usuario ha seleccionado una fila de GridView, es necesario mostrar los productos de proveedor seleccionados. En algunas circunstancias, es posible que deseemos mostrar estos productos en una página independiente, en otros, es posible que prefiera hacerlo en la misma página. Vamos a examinar primero cómo mostrar los productos en una página independiente. en el paso 5 veremos cómo agregar un control GridView a RadioButtonField.aspx para mostrar los productos de proveedores seleccionados.

Actualmente hay dos controles Web de botón en la página ListProducts y SendToProducts. Cuando se hace clic en el botón SendToProducts, queremos enviar al usuario a ~/Filtering/ProductsForSupplierDetails.aspx. Esta página se ha creado en el tutorial de filtrado maestro y detalles en dos páginas y muestra los productos del proveedor cuyo SupplierID se pasa a través del campo querystring denominado SupplierID.

Para proporcionar esta funcionalidad, cree un controlador de eventos para el evento SendToProducts botón s Click. En el paso 3 se ha agregado la propiedad SuppliersSelectedIndex, que devuelve el índice de la fila cuyo botón de radio está seleccionado. El SupplierID correspondiente se puede recuperar de la colección de DataKeys de GridView y, a continuación, el usuario se puede enviar a ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID mediante Response.Redirect("url").

protected void SendToProducts_Click(object sender, EventArgs e)
{
    // Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
    int supplierID = 
        Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
    Response.Redirect(
        "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" 
        + supplierID);
    }
}

Este código funciona de forma maravillosa siempre que se seleccione uno de los botones de radio de GridView. Si, inicialmente, GridView no tiene ningún botón de radio seleccionado y el usuario hace clic en el botón SendToProducts, SuppliersSelectedIndex se -1, lo que hará que se produzca una excepción, ya que -1 está fuera del intervalo de índices de la colección DataKeys. Sin embargo, esto no es un problema, si decide actualizar el controlador de eventos RowCreated como se describe en el paso 3 para que el primer botón de radio de GridView esté seleccionado inicialmente.

Para dar cabida a un valor SuppliersSelectedIndex de -1, agregue un control Web de etiqueta a la página sobre GridView. Establezca su propiedad ID en ChooseSupplierMsg, su propiedad CssClass en Warning, sus propiedades EnableViewState y Visible en falsey su propiedad Text para elegir un proveedor de la cuadrícula. La clase CSS Warning muestra texto en una fuente de color rojo, cursiva, negrita y grande, y se define en Styles.css. Al establecer las propiedades EnableViewState y Visible en false, la etiqueta no se representa excepto solo para los postbacks en los que la propiedad control s Visible se establece mediante programación en true.

agregar un control Web de etiqueta sobre GridView

Figura 13: agregar un control Web de etiqueta sobre GridView (haga clic para ver la imagen de tamaño completo)

A continuación, aumente el controlador de eventos Click para mostrar la etiqueta de ChooseSupplierMsg si SuppliersSelectedIndex es menor que cero y redirija al usuario a ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID en caso contrario.

protected void SendToProducts_Click(object sender, EventArgs e)
{
    // make sure one of the radio buttons has been selected
    if (SuppliersSelectedIndex < 0)
        ChooseSupplierMsg.Visible = true;
    else
    {
        // Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
        int supplierID = 
            Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
        Response.Redirect(
            "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" 
            + supplierID);
    }
}

Visite la página en un explorador y haga clic en el botón SendToProducts antes de seleccionar un proveedor de GridView. Como se muestra en la figura 14, se muestra la etiqueta ChooseSupplierMsg. A continuación, seleccione un proveedor y haga clic en el botón SendToProducts. Esto le indicará a una página que muestra los productos suministrados por el proveedor seleccionado. En la figura 15 se muestra la página ProductsForSupplierDetails.aspx cuando se seleccionó el proveedor de Breweries de Bigfoot.

se muestra la etiqueta ChooseSupplierMsg si no se selecciona ningún proveedor

Figura 14: el ChooseSupplierMsg etiqueta se muestra si no se selecciona ningún proveedor (haga clic para ver la imagen de tamaño completo)

los productos de proveedores seleccionados se muestran en ProductsForSupplierDetails. aspx

Figura 15: los productos de proveedores seleccionados se muestran en ProductsForSupplierDetails.aspx (haga clic para ver la imagen de tamaño completo)

Paso 5: mostrar los productos de proveedores seleccionados en la misma página

En el paso 4, vimos cómo enviar al usuario a otra página web para mostrar los productos de proveedores seleccionados. Como alternativa, los productos de los proveedores seleccionados se pueden mostrar en la misma página. Para ilustrar esto, agregaremos otro GridView a RadioButtonField.aspx para mostrar los productos de proveedor seleccionados.

Puesto que solo queremos que este GridView de productos se muestre una vez que se ha seleccionado un proveedor, agregue un control Web panel debajo del Suppliers GridView, estableciendo su ID en ProductsBySupplierPanel y su propiedad Visible en false. En el panel, agregue los productos de texto para el proveedor seleccionado, seguido de un control GridView denominado ProductsBySupplier. En la etiqueta inteligente de GridView s, elija enlazarla a un nuevo ObjectDataSource denominado ProductsBySupplierDataSource.

enlazar el control GridView ProductsBySupplier a un nuevo ObjectDataSource

Figura 16: enlace de la ProductsBySupplier GridView a un nuevo ObjectDataSource (haga clic para ver la imagen de tamaño completo)

A continuación, configure ObjectDataSource para usar la clase ProductsBLL. Puesto que solo queremos recuperar los productos proporcionados por el proveedor seleccionado, especifique que ObjectDataSource debe invocar el método GetProductsBySupplierID(supplierID) para recuperar sus datos. Seleccione (ninguno) en las listas desplegables de las pestañas actualizar, insertar y eliminar.

configurar ObjectDataSource para usar el método GetProductsBySupplierID (supplierID)

Figura 17: configuración de ObjectDataSource para usar el método GetProductsBySupplierID(supplierID) (haga clic para ver la imagen de tamaño completo)

establecer las listas desplegables en (ninguna) en las pestañas actualizar, insertar y eliminar

Figura 18: establezca las listas desplegables en (ninguna) en las pestañas actualizar, insertar y eliminar (haga clic para ver la imagen a tamaño completo)

Después de configurar las pestañas seleccionar, actualizar, insertar y eliminar, haga clic en siguiente. Dado que el método GetProductsBySupplierID(supplierID) espera un parámetro de entrada, el Asistente para crear orígenes de datos le pide que especifique el origen del valor del parámetro s.

Tenemos un par de opciones aquí para especificar el origen del valor del parámetro s. Podríamos usar el objeto de parámetro predeterminado y asignar mediante programación el valor de la propiedad SuppliersSelectedIndex a la propiedad Parameter s DefaultValue del controlador de eventos ObjectDataSource s Selecting. Vuelva a consultar la configuración mediante programación del tutorial de valores de parámetro de ObjectDataSource para un actualizador en la asignación mediante programación de valores a los parámetros de ObjectDataSource s.

Como alternativa, podemos usar ControlParameter y hacer referencia a la propiedad Suppliers GridView s SelectedValue (consulte la figura 19). La propiedad GridView s SelectedValue devuelve el valor de DataKey correspondiente a la propiedadSelectedIndex. Para que esta opción funcione, es necesario establecer mediante programación la propiedad SelectedIndex de GridView en la fila seleccionada cuando se haga clic en el botón ListProducts. Como ventaja adicional, si se establece el SelectedIndex, el registro seleccionado tomará el SelectedRowStyle definido en el tema de DataWebControls (un fondo amarillo).

usar ControlParameter para especificar GridView s SelectedValue como el origen del parámetro

Figura 19: uso de ControlParameter para especificar el control GridView s como el origen del parámetro (haga clic para ver la imagen de tamaño completo)

Al finalizar el asistente, Visual Studio agregará automáticamente campos para los campos de datos de los productos. Quite todos los ProductName, CategoryNamey UnitPrice BoundFields, y cambie las propiedades de HeaderText a product, Category y price. Configure el UnitPrice BoundField para que su valor tenga el formato de moneda. Después de realizar estos cambios, el marcado declarativo del panel, GridView y ObjectDataSource debe ser similar al siguiente:

<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 completar este ejercicio, es necesario establecer la propiedad GridView s SelectedIndex en el SelectedSuppliersIndex y la propiedad Visible del panel ProductsBySupplierPanel en true al hacer clic en el botón ListProducts. Para ello, cree un controlador de eventos para el evento de control Web Button ListProducts Click y agregue el código siguiente:

protected void ListProducts_Click(object sender, EventArgs e)
{
    // make sure one of the radio buttons has been selected
    if (SuppliersSelectedIndex < 0)
    {
        ChooseSupplierMsg.Visible = true;
        ProductsBySupplierPanel.Visible = false;
    }
    else
    {
        // Set the GridView's SelectedIndex
        Suppliers.SelectedIndex = SuppliersSelectedIndex;
        // Show the ProductsBySupplierPanel panel
        ProductsBySupplierPanel.Visible = true;
    }
}

Si no se ha seleccionado un proveedor de GridView, se muestra la etiqueta de ChooseSupplierMsg y se oculta el panel de ProductsBySupplierPanel. De lo contrario, si se ha seleccionado un proveedor, se muestra el ProductsBySupplierPanel y se actualiza la propiedad SelectedIndex de GridView.

En la figura 20 se muestran los resultados una vez que se ha seleccionado el proveedor de Bigfoot Breweries y se ha realizado un clic en el botón Mostrar productos en la página.

los productos proporcionados por Bigfoot Breweries se muestran en la misma página

Figura 20: los productos proporcionados por Bigfoot Breweries aparecen en la misma página (haga clic para ver la imagen a tamaño completo)

Resumen

Tal y como se describe en el tutorial maestro y detalles con un control GridView de la página maestra seleccionable con un DetailView de detalles , los registros se pueden seleccionar en un control GridView mediante un CommandField cuya propiedad ShowSelectButton esté establecida en true. Sin embargo, el CommandField de instalación de muestra los botones como botones de envío, vínculos o imágenes normales. Una interfaz de usuario de selección de fila alternativa consiste en proporcionar un botón de radio o una casilla en cada fila de GridView. En este tutorial, hemos examinado cómo agregar una columna de botones de radio.

Desafortunadamente, agregar una columna de botones de radio no es tan sencillo o sencillo como cabría esperar. No hay ningún RadioButtonField integrado que se pueda agregar al hacer clic en un botón y el uso del control Web RadioButton dentro de TemplateField incluye su propio conjunto de problemas. Al final, para proporcionar una interfaz de este tipo, es necesario crear una clase de DataControlField personalizada o volver a insertar el HTML adecuado en TemplateField durante el evento RowCreated.

Una vez que se ha explorado cómo agregar una columna de botones de radio, preste atención a la adición de una columna de casillas. Con una columna de casillas, un usuario puede seleccionar una o más filas de GridView y, a continuación, realizar alguna operación en todas las filas seleccionadas (por ejemplo, seleccionar un conjunto de correos electrónicos de un cliente de correo electrónico basado en Web y, a continuación, seleccionar eliminar todos los correos electrónicos seleccionados). En el siguiente tutorial, veremos cómo agregar este tipo de columna.

¡ Feliz programación!

Acerca del autor

Scott Mitchell, autor de siete libros de ASP/ASP. net y fundador de 4GuysFromRolla.com, ha estado trabajando con las tecnologías Web de Microsoft desde 1998. Scott funciona como consultor, profesor y redactor independiente. Su último libro se enseña a ASP.NET 2,0 en 24 horas. Puede ponerse en contacto con usted en mitchell@4GuysFromRolla.com. o a través de su blog, que encontrará en http://ScottOnWriting.NET.

Agradecimiento especial a

Muchos revisores útiles revisaron esta serie de tutoriales. El revisor responsable de este tutorial fue David Suru. ¿Está interesado en revisar los próximos artículos de MSDN? En caso afirmativo, suéltelo en mitchell@4GuysFromRolla.com.