lunes, 12 de julio de 2010

[ASP.NET][GridView] Edición usando DropDownList

 

Introducción


La edición de entidades directamente en el control GridView puede requerir algunas adaptaciones que adecuen la grilla a la funcionalidad requerida dependiendo de la información que se quiera mostrar.

Dos puntos importantes cuando uno utiliza el control GridView son:

- Adecuar el control usado para desplegar la información al usuario.

En el ejemplo se explicara como cambiar el control de edición por defecto, o sea un TextBox, que se desplegaría al usuario, por otro especialmente definido para la selección por medio de un ítem concreto, por medio de un DropDownList.

- La definición de un identificador para cada registro de la grilla, sin necesidad de desplegar este al usuario.

Se suele necesitar un id o clave que permita identificar el registro, pero que este no se muestre al usuario, sino que sea de uso interno.

 

Definición del ejemplo


El mismo consiste en una lista de contactos a los cuales se le podrá asignar el país de nacimientos.

Durante la edición se desplegara al usuario un cuadro de texto en donde podrá cambiar el nombre, pero los países estarán definidos en una lista desplegable desde la cual serán seleccionados.

Imagen1

 

Edición mediante un DropDownList


Si se analiza la definición del Gridview se notara que es por medio de un control DropDownList en el tag <EditItemTemplate> que se define la lista de países.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
     AutoGenerateEditButton="True" CellPadding="4" ForeColor="#333333" GridLines="None"
     DataKeyNames="id" 
     onrowediting="GridView1_RowEditing"
     onrowcancelingedit="GridView1_RowCancelingEdit" 
     onrowupdating="GridView1_RowUpdating">
     <RowStyle BackColor="#EFF3FB" />
     <Columns>
         <asp:BoundField DataField="nombre" HeaderText="Nombre Usuario" />
         <asp:TemplateField HeaderText="Pais Nacimiento">
             <EditItemTemplate>
                 <asp:DropDownList ID="ddlPaises" runat="server">
                 </asp:DropDownList>
             </EditItemTemplate>
             <ItemTemplate>
                 <asp:Label ID="Label1" runat="server" Text='<%# Bind("descripcion") %>'></asp:Label>
             </ItemTemplate>
         </asp:TemplateField>
     </Columns>
     <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
     <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
     <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
     <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
     <EditRowStyle BackColor="#2461BF" />
     <AlternatingRowStyle BackColor="White" />
 </asp:GridView>

Además la columna completa ha cambiado ya no es es mas BoundField, el cual mostraría un simple TextBox durante la edición, sino que se define todo un témplate, mediante el tag <TemplateField>.

Mediante la propiedad AutoGenerateEditButton se indica que en la grilla estén definidos las opciones de edición, por lo tanto habrá ciertos eventos que será necesario agregar en el código.

Es muy importante tener en cuenta que la carga de la información de la grilla solo se realice una vez al inicio de la pagina.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        BindData();
    }
}

private void BindData()
{
    GridView1.DataSource = DataAccess.GetAllUsuario();
    GridView1.DataBind();
}

Es por eso que el evento Load de la pagina define la carga de los datos de la grilla dentro del bloque IsPostBack, le cual tiene que estar negado, ya que solo durante la carga inicial del formulario será requerida esta operación.

La primer acción que se expone al usuario es la edición, que efectuara el cambio al edittemplate, pero antes ejecutara el evento:

protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
    GridView1.EditIndex = e.NewEditIndex;

    int id = Convert.ToInt32(GridView1.DataKeys[e.NewEditIndex].Value);
    DataRow row = DataAccess.GetUsuarioById(id);

    BindData();

    DropDownList combo = GridView1.Rows[e.NewEditIndex].FindControl("ddlPaises") as DropDownList;

    if (combo != null)
    {
        combo.DataSource = DataAccess.GetAllPaises();
        combo.DataTextField = "descripcion";
        combo.DataValueField = "id";
        combo.DataBind();
    }

    combo.SelectedValue = Convert.ToString(row["pais"]);
}

En este evento se recupera el id del contacto que representa la fila en edición, se cargan los ítems en el combo para esa fila, y por ultimo se asigna la selección del país que actualmente esta definido la entidad del contacto. Un link interesante que puede ayudar es el siguiente: GridView.RowEditing Event

Debe recordarse que en principio el DropDownList no tiene registros u opciones definidas, es en este evento donde se asignan.

Es importante notar que por medio de la propiedad EditIndex del GridView, se define que fila cambia de estado.

Luego de editar el registro, se disponen de dos acciones, actualizar o cancelar, para lo cual se disponen los eventos:

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    int id = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);

    DropDownList combo = GridView1.Rows[e.RowIndex].FindControl("ddlPaises") as DropDownList;
    int pais = Convert.ToInt32(combo.SelectedValue);

    TextBox text = GridView1.Rows[e.RowIndex].Cells[1].Controls[0] as TextBox;
    string nombre = text.Text;

    DataAccess.UpdateUsuario(id, nombre, pais);

    GridView1.EditIndex = -1;
    BindData();

}

protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
    GridView1.EditIndex = -1;
    BindData();
}

La edición recupera la información asignada a los controles de la fila activa, y se procede a invocar a la capa de datos para actualizar la entidad.

Conociendo la fila que lanza el evento de actualización, por medio de e.RowIndex, y pudiendo buscar el control mediante su nombre, es que se recupera el valor seleccionado del combo.

En cambio el nombre al estar definido en un BoundField, se recupera mediante el acceso a la celda y a la colección de controles definidos en este, pero como es sabido que solo contendrá un control, o sea el TextBox donde se edita el nombre.

Por ultimo mediante la propiedad EditIndex de la grilla, se deja de editar la fila, es preciso notar que luego de cada operación la información se vuelve a bindear.

 

Definición del Identificador de la fila


Una característica importante del GridView es la posibilidad de definir que propiedad del origen de datos que actuara como identificador de la entidad.

En el ejemplo seguramente se habrá notado la definición de la propiedad DataKeyNames, la cual define el “id” como identificador de cada registro.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
       AutoGenerateEditButton="True" CellPadding="4" ForeColor="#333333" GridLines="None"
      
DataKeyNames="id"
       onrowediting="GridView1_RowEditing"
       onrowcancelingedit="GridView1_RowCancelingEdit"
       onrowupdating="GridView1_RowUpdating">

Esto es clave para poder recuperar la información del contacto en cada acción realizada por el control. Por medio de DataKeys, es que se obtiene el valor asociado a una fila en particular.

En el código de cada evento se uso de la siguiente forma:

int id = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);

Es necesario conocer que fila que se esta editando para recuperar de la colección de claves el valor concreto.

 

Acerca del ejemplo


El mismo fue creado usando VS2008 y Sql Server Express 2008

Sera necesario tener el servicio de Sql Server local para que pueda ejecutarse la aplicación

 

[C#] 
[VB.NET] 

145 comentarios:

  1. Leandro...
    y cual es la diferencia entre usar el DataKey a usar el siguiente código:

    Dim codigo As Label = grvPeople.Rows(e.RowIndex).FindControl("lblCodigo")


    el cual luego codigo.Tex lo convierto en Integer
    siendo código mi PK.

    ???

    ResponderEliminar
    Respuestas
    1. alguin me puede ayudar von un proyecto en aspet

      Eliminar
  2. hola LiZzY

    La diferencia es que con el DataKey no estas obligado a mostrar el campo con el codigo del item que se representa en la fila de la grilla.

    En cambio si seleccionas con el FindControl(), si o si esa columna debera estar visible al usuario.

    Si en tu caso sabes que el id, o codigo, esta en una columna, puede que no necesites el DataKey, pero si quieres identificar el registro inequivocamente sin mostrar ese campo, usa el DataKey.

    Pasa por un tema de visibilidad de la informacion.

    Aunque nada impide que tengas el DataKey y ademas muestres el campo del codigo.

    saludos

    ResponderEliminar
  3. Hola Leandro.
    Ojala me puedas ayudar.

    Tengo 2 DropDownList anidados (ASP.NET), usando el cascading de AJAX me funciona el anidamiento ok; pero me hace falta, luego que el segundo ddl se llena ejecutar una funcion en JavaScript que me va a deshabilitar determinados campos.
    Cuando se llena en dependencia del 1 ddl el onchange del 2 ddl no se ejecuta.
    ¿Tienes alguna idea de como puedo lograrlo?
    Gracias...

    ResponderEliminar
  4. hola Sandra

    disculpa la demora en la respuesta

    El tema es que al usar ajax no hay un refresh de la pagina que pudiera invocar el javascript cuando se devuelva la lista del segundo combo

    Por ahi deberas enviar un script especial desde el servidor usando el ScriptManager invocando a ese metodo de javascript que quieres ejecutar despues de la carga del combo.

    En este link veras como usar el ScriptManager:
    [ASP.NET] - JavaScript alert() y confirm()

    y armar algo como ser

    (script type='text/javascript')
    FuncionJavascript();
    (/script)

    como veras en FuncionJavascript() iria el nombre de la funcion que quieres eejcutar luego de la carga de la lista.

    Nota, use los () en lugar de los <> porque sino no me dejaba publicar

    saludos

    ResponderEliminar
  5. Hola Leandro:

    Gracias por la respuesta, resuelto totalmente el problema.
    Gracias de nuevo!!!

    Saludos

    ResponderEliminar
  6. Disculpa mi molestia,tengo una duda: en un datagrid tengo dos dropdownlist, uno me carga ciertos nombres de empresas cuando entra en modo de edicion,pero ahora no se como hacer que me cargue el otro dropdownlist pasandole como parametro el codigo de una empresa que se encuentra en el primer dropdownlist tambien en modo de edicion,podrias ayudarme o darme un pista

    ResponderEliminar
  7. hola

    Segun veo lo que quieres hacer es relacionar o anidar el contenido de un combo con el del otro, ambos integrados en un GridView

    En este otro post explique como relacionar combos:
    [ASP.NET] DropDownList anidados

    pero aqui hay un tema y es que estan dentro del Gridview.

    para poder hacerlo seguramejnte debas al moneto que cargas los items del combo cuando entra en edicion, asignar la propiedad AutoPostBack del primer combo y ademas que este tenga definido el evento SelectedIndexChanged

    aunque tambien podrias probar de asignar tanto el evento como el AutoPostBack directo desde el diseño

    Entonces cuando se presione el item, en el SelectedIndexChanged, usa el argument sender
    para obtener el segundo comno deberia usar el
    GridView.SelectedRow Property

    junto al FindControl() para recuperar el combo que recibira la carga de los items

    de esta forma tendrias el evento SelectedIndexChanged asociado al primer combo, y con el sender tomarias el SelectedValue, y con el SelectedRow y el FindControl() tomarias el segundo combo para cargar los datos

    saludos

    ResponderEliminar
  8. Ok muchas gracias, voy a probar con eso y posteriormente te escribo los resultados,de antemano muchas gracisa, Saludos!

    ResponderEliminar
  9. Aqui tengo mi plantilla:



    <%#Container.DataItem("empresa")%>







    ya le he asignado lo del postaback y el evento,pero no se como usar el sender, o el sender de quien,me imagino que corresponde al evento del grid, ah pero yo uso un datagrid y no un gridview

    ResponderEliminar
  10. LEANDRO....
    BUEN CODIGO MUCHAS GRACIAS POR AYUDARNOS A TODOS. DEBO DE HACER UN EDIT DESDE EL GRIDVIEW PERO A LA BD, MI DATASOURCE ES UN DATATABLE, DOS SON MIS LLAVES PRIMARIAS POR DECIRLO A SI EL NUM TABLA ES LA PRIMERA, Y ELEMENTO ES LA SEGUNDA EL DATAKEY ME SIRVE PARA EL NUM_TABLA, PERO NECESITO HACER UN AND CON ELEMENTO PARA MODIFICAR ESA COLUNA. CABE MENCIONAR QUE PUEDO MODIFICAR LOS DATOS DE ELEMENTO PERO NO LOS DE NUMTABLA, PUEDO TENER MUCHOS REGISTROS CON NUMTABLA, PERO SOLO UNO CON ELEMENTO, COMO PUEDO OBTENER EL VALOR DEL ELEMENTO QUE DESEO MODIFICAR ANTES DE MODIFICARLO

    ResponderEliminar
  11. hola leandro muy buenoes tips los tuyos y aprovechando una pregunta, ay o abra alguna forma de enviar una fila de un gridview a crystal report???? es q estando en el grid, debo seleccionar un registro y ese seleccionado, ir a crystal, ojala puedas ayudarme gracias

    ResponderEliminar
  12. hola Cris

    Como poder, se puede, solo que deberias conectar el reporte de Crystal a un dataset tipado y agregar la info programaticamente, o sea sin vincular el DataSet a uan db sino que crearias el registro por codigo
    Luego se lo pasas al crystal para lanzar el reporte.

    En este otro ejemplo lo realice con un DataGridview, bien aqui seria la misma tecnica, solo que tomarias la info de la seleccion del GridView.

    [Crystal Reports] - Exportar DataGridView a Crystal

    saludos

    ResponderEliminar
  13. Hola Leandro , estuve tratando de utilizar este ejemplo pero no he podido ejecutarlo ,creo que es por la bd .mdf , podrías pasar un script o de que manera se puede solucionar porque lo he probado en sql 2005 y 2008 y no he pdodido acceder a la data.
    Saludos.

    ResponderEliminar
  14. Hola Leandro,

    Una pregunta tengo un gridview con varios campos, lo que quiero hacer es modificar un unico campo con un templatefield y un buttonfield, en el templefield tengo el valor del campo y cuando le doy al buttonfield lo actualizo, pero en el templefield no me coge el nuevo valor que introduzco.











    Private Sub grdActividades_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grdActividades.RowCommand
    If e.CommandName = "Modificar" Then
    Dim Text As TextBox = TryCast(grdActividades.Rows(e.CommandArgument).Cells(4).Controls(1), TextBox)
    Dim Prioridad As String = Text.Text
    MsgBox(Prioridad)
    End If

    End Sub

    Gracias

    ResponderEliminar
  15. hola Diego

    Es que deberia hacer uso del FindControl()

    algo como esto

    Dim row As GridViewRow = grdActividades.Rows(e.CommandArgument)

    Dim Text As TextBox = TryCast(row.FindControl("TextBox1"), TextBox)


    Eso si primero valida que el row se este seleccionando correctamente, y ademas reemplaza el nombre que le has dado a ese TextBox, en el metodo FindControl()

    saludos

    ResponderEliminar
  16. Hola Leandro, gracias por tu codigo me esta ayudando harto, sin embargo cuando lo ejecuto tengo un mensaje de error:

    Referencia a objeto no establecida como instancia de un objeto.
    Línea 54: Dim nombre As String = text.Text

    A que crees que se deba, ojo no estoy usando tu sub rowdatbound por que estoy llenando el dropdownlist directamente con asp.net

    ResponderEliminar
  17. hola Monica y Daniel

    lo mas probable es que se deba a que la liena previa

    Dim text As TextBox = TryCast(GridView1.Rows(e.RowIndex).Cells(1).Controls(0), TextBox)

    no este encontrando el control textbox, y como se hace uso del TryCast() este no falla sino que devuelve un Nothing como respuesta

    es por eso que si en la variable "text" hay un nothing al acceder a la propiedad Text se genere ese problema

    Valida que se esta encotnrando correctamente el control que requieres, puedes hacer uso del FindControl() si necesitas hacerlo por nombre

    saludos

    ResponderEliminar
  18. Hola Leo, otra vez por aquí con una consulta :( .
    Sobre lo de volver a Bindear la información luego de cada una de la operaciones(Edit,Update y Cancel) entiendo que es necesario ya que la información solo se bindea una vez en el evento Load, pero lo que no me queda claro es porque solo en el evento gvEdicion_RowEditing se tiene que llamar a BindData() justo antes de recuperar el combo "ddlPaises", porque de otra forma no lo encuentra y devuelve Nothing,Como es que sin necesidad de volver a bindear si se encuentra el DataKeys, pero no el combo que ni siquiera toma ningún dato de los que proporciona BindData()??
    Por qué es completamente necesario el bindeo justo antes de recuperar el combo si por ejemplo he notado que si lo pongo al final del evento, el combo aparece(vació pero aparece)en el código fuente, pero aun así para el programa simplemente no existe y devuelve Nothing??

    Gracias de antemano y espero no causar molestias con tantas preguntas que he venido haciendo últimamente

    ResponderEliminar
  19. hola Alexandra

    la verdad nunca he analizado por dentro como es que reprsenta la informacion el control, pero viendo un poco imagino que el DataKeys se mentiene en una coleccion separada de datos que viaja con el viewstate, por eso puede accederlo directo

    en cambio recuerda que el grid hasta antes de ponerle el index del row a editar, la fila tenia un template distinto para esa row,
    al bindearlo estas renderizando las fila nuevamente y esta pasa a edicion cambiando el tempalte que la representa, por lo tanto ahi es cuando se vuelve accedible el combo, hasta antes de esto no estaba representado en el grid

    si queria solo acceder a el label de informacion de esa row no tenias porque recargarlo, pero como le cambias el estado, necesitas recargarlo para que lo aplique y pase de ItemTemplate a EditItemTemplate y se pueda asi tomar el combo para cargarlo

    has la prueba en ese evento de edicion, no hacer la recarga y usa el FindControl() con el Label1, sino yerro en la teoria deberias poder accederlo y tomar la info del mismo
    solo la recarga pasa de tempalte la fila y asi accedes al combo

    saludos

    ResponderEliminar
  20. Tenias razón, creo que mi error partía de que equivocadamente creía que por el simple hecho de asignar el indice de la fila al EditIndex automáticamente se entraba al y por lo tanto el combo ya estaba disponible, lo comprobé con lo que sugeriste de recuperar el label y efectivamente éste estaba disponible con lo cual quedaba completamente comprobado que aun me encontraba en .
    Lo que no me deja de sorprender es lo que sucede "Behind the scenes", para que sin volver a recargar la pagina se renderisan los controles de edición y se ponen a disposición del evento :O

    Gracias y saludos

    ResponderEliminar
  21. Una preguntita mas :$, viendo lo que sugeriste de tratar de recuperar el label, cuando lo intente recuperar mediante la colección de controles de la celda, no se supone que solo hay un control?? y que podría acceder de esta forma
    TryCast(gvEdicion.Rows(e.NewEditIndex).Cells(2). Controls(0), Label) ?? Osea con el indice 0(cero), pero por alguna razón solo pude acceder con el indice 1 :
    TryCast(gvEdicion.Rows(e.NewEditIndex).Cells(2). Controls(1), Label).

    Saludos y disculpa que sea tan preguntona ;)

    ResponderEliminar
  22. hola Alexandra

    claro la forma de acceder a los controels desde la coleccion Controls() tambien es valida

    Particularmente me gusta mas la del findControl() porque es como que quedaria bien marcado que control recuperas, pero usar el indice tambien es valido

    Me llama la atencion que con el cero no toma el Label, si es el unico control en la celda deberia ser el cero.

    Podrias ver de usar
    gvEdicion.Rows(e.NewEditIndex).Controls.Count()

    y poner la cantidad en algun textbox u otro control para ver cuantos controles reconoce

    Tambien podrias usar
    GridView1.Rows(0).Cells(0).Controls(0).GetType()

    y ver que tipo devuelve para conocer de que control esta tomando en el indice cero


    saludos

    ResponderEliminar
  23. Hola Leo hice los que me recomendaste y puse el cantidad de controles en un textbox y los tipos de los controles en un textarea y esto es lo que obtuve:

    Cantidad de Controles: 3

    Tipos de Controles:
    Indice :0 - Tipo :System.Web.UI.LiteralControl
    Indice :1 - Tipo :System.Web.UI.WebControls.DropDownList
    Indice :2 - Tipo :System.Web.UI.LiteralControl

    Lo anterior es si llamo a BindData() sino llamo a ese procedimiento lo que obtengo es muy similar, también tres controles con la diferencia que el de indice 1 es de tipo :System.Web.UI.WebControls.Label.

    Lo curioso es que también hice la prueba para el BoundField "Nombre" y ese si me devuelve un único control a diferencia del TemplateField, tendrá algo que ver los tipos de columnas??

    Saludos y nuevamente gracias ;)

    ResponderEliminar
  24. hola Alexandra

    claro el tema es que el BoundField define el template el propio grid, en cambio en el TemplateField, tu lo defines, pero se ve que deja controles de texto delante y detras del control que tu incluyes

    en ese caso es tan simples como usar

    DropDownlist combo = gvEdicion.Rows(e.NewEditIndex).Controls[1] as DropDownlist;

    como veras use Controls[1], porque es alli donde esta ubicado en la coleccion

    aunque creo que seria mejor usar el FindControl()

    saludos

    ResponderEliminar
  25. Hola Leandro.

    aunque creo que seria mejor usar el FindControl()
    de hecho yo también prefiero usar FindControl, solo pregunte porque me parecía extraño que haya mas de un control en las celdas del TemplateField y quería saber si por algún lugar(documentación en linea,libro, etc) se indicaba este comportamiento con el TemplateField.

    Saludos y muchas gracias.

    ResponderEliminar
  26. Ah tengo una dudota, ahebr si me puedes ayudar tengo casi lo mismo que tu en el ejemplo pero me marca error con DropDownList la hacer el update, lo debuggeo y se ejecuta 2 veces es como si el GVautorizacion.EditIndex = -1 no me scara de la edicion, entra la 1era vez toma los datos y actualiza pero vuelve a entrar y cuando quiere recoger la informacion del DropDownlist marca null reference, tienes idea de porq pasa esto o comopodria solicionarlo?

    ResponderEliminar
  27. hola Patsy539

    estas haciendo esto en los eventos correctos ?

    o sea haces esto en el evento RowUpdating del grid, es alli donde tomas el valor del combo actualizas y para quitar la edicion lo pones en -1, pero tambien recargas los datos del grid ?

    saludos

    ResponderEliminar
  28. si mira este es mi emtodo completo
    Protected Sub GVautorizacion_RowUpdating(sender As Object, e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GVautorizacion.RowUpdating
    Dim fila As GridViewRow = GVautorizacion.Rows(e.RowIndex) 'Se recupera la fila q se esta editando

    If fila IsNot Nothing Then
    Dim NoCliente As String = GVautorizacion.DataKeys(fila.RowIndex).Value.ToString()
    Dim NoCadena As String = TryCast(fila.FindControl("LbNoCadena"), Label).Text
    Dim NoPoCli As String = TryCast(fila.FindControl("LbNoPoCli"), Label).Text
    Dim FechaVence As String = TryCast(fila.FindControl("TxtFechaVence"), TextBox).Text
    Dim TipoOrden As String = TryCast(fila.FindControl("DdlTipoOrden"), DropDownList).SelectedValue
    'Dim TipoOrden As String = TryCast(GVautorizacion.Rows(e.RowIndex).FindControl("DdlTipoOrden"), DropDownList).SelectedValue
    Dim TipoEntrega As String = TryCast(fila.FindControl("DdlTipoEntrega"), DropDownList).Text
    Dim query As String = "UPDATE SWOrdenes SET TipoOrden='" & TipoOrden & "', TipoEntrega='" & TipoEntrega & "', Status='R'" &
    "FechaVence='" & FechaVence & "' WHERE NoCliente='" & NoCliente & "' AND NoCadena='" & NoCadena & "' AND NoPoCli='" & NoPoCli & "'"
    trans = New Transacciones()
    Dim actualizo As String = trans.loadFromSqlNoExec(query, Nothing, CommandType.Text).ToString()
    If Not IsNumeric(actualizo) Then
    Label1.Text = "Error al actualizar la orden del cliente"
    End If
    GVautorizacion.EditIndex = -1 'para salir del estado de edición
    llenarAutorizacion()
    End If
    End Sub

    No entiedno porq se ejecuta 2 veces, no creo q tenga algo que ver q esta dentro de update panel el gridview.... le encuestras alguna razon para que pase eso se ejecute 2 veces....

    ResponderEliminar
  29. Hola Leandro , soy principiante, tengo un webform con un control checkboxlist,dropdonwlist, uno del rango de fechas, y quiero que mostrar esos controles en una grilla.
    nose como obtener el valor seleccionado para mostrarlos a traves de un boton en una grilla, graacias.

    ResponderEliminar
  30. hola ivan

    la tecnica es la misma, debes situar esos controles en el TemplateField que define la columna del gridview, tal cual lo hice con el combo del ejemplo

    por supuesto estos actuaran cuando entre en edicion el grid, pero si lo defines en el ItemTemplate estaran siempre activos

    imagino que cada control sera una columan diferente

    usa el FindControl() para ubicar y trabajar cada control de la row activa

    saludos

    ResponderEliminar
  31. Hola Leandro, quería agradecerte por la publicación en verdad que me ha servido mucho, pero tengo un problemita, lo que pasa es que quiero eliminar datos de la Grilla, pero NO quiero que me los elimine inmediatamente al presionar Eliminar, pues sería bueno y seguro que me preguntase que Si en verdad deseo eliminarlo!!! he pensado que se puede hacer con JS, pero sería mejor si se pudiera utilizar controles del mismos Visual Studio!! de todas maneras te agradezco mucho...

    SALUDOS!

    ResponderEliminar
  32. hola AlejoNait

    El tema es que el mensaje que mostrarias se ejecuta en el cliente, por eso es javascript

    [GridView] Javascript botón de eliminar con confirmación

    saludos

    ResponderEliminar
  33. Hola Leandro,
    Tengo un problema grande con extrapolar este código a un Listview, donde no hay Rows a buscar. ¿Cómo se podría insertar un DropDownList en un listview?

    Me descargue la versión de Gridview pero no funciona con Listview.

    Mil gracias.

    ResponderEliminar
  34. hola Carlos

    El control ListView al igual que el GridView permiten definir template para definir el formato del contenido
    es en este que deberias colocar el DropDownList

    DropDownList in ListView ItemTemplate

    dentro del ItemTemplate podrias definir alli el combo

    saludos

    ResponderEliminar
  35. Hola Leandro muchas gracias por compartir tu conocimiento. Saludos!

    ResponderEliminar
  36. Leandro Gracias por el Aporte

    Tengo un inconveniente estoy utilizando un gridview con paginacion,si por ejemplo das clic para cambiar la información del dropdownlist y no la cambias y pasas a otra pagina el dropdownlist se queda en blanco.

    ResponderEliminar
  37. hola

    queda en blanco en la nueva pagina a la cual se dirige el paginado, o queda en blanco cuando vuelves a la pagina anterior ?

    lo pregunto porque se supone que la pagina se deberia anular la edicion del registro

    y al ponerlo en edicion nuevamente debes tomar la row que se edita y cargar los items del dropdown list

    por eso es raro que queda en blanco

    saludos

    ResponderEliminar
  38. Este queda en blanco en la nueva pagina a la cual se dirige el paginado.

    ResponderEliminar
  39. hola Posvaldo

    la verdad no entendi, no me gago la idea de que es lo que queda en blanco, si es la pagina o si es el combo

    no te animas a plantearlo en el foro

    Foro asp.net

    alli puede subir una imagen de lo que sucede asi se puede analizar con mas detalle, por este medio se va a complicar publicar una imagen

    saludos

    ResponderEliminar
  40. Muchas Gracias Leandro ya pude resolverlo,lo que tuve que hacer fue en el evento del Gridview
    PageIndexChanging, mandar a llenar nuevamente el combo con las opciones.

    ResponderEliminar
  41. Seguí los pasos, pero al final el DDL se muestra vacío

    ResponderEliminar
  42. hola Omar

    al final de que operacion queda vacio?

    en que evento cvargas el gridview, es en el Page_Load? porque si es asi recuerda usar el

    if(!IsPostBack){
    //aqui cargas el gridview
    }

    sino haces eso en cada accion se recargara perdiendo los datos

    saludos

    ResponderEliminar
  43. Man gracias por el ejemplo, me sirvió muchísimo, lo pude acomodar a lo que yo ocupaba, saludos!!

    ResponderEliminar
  44. Tengo un gridview en la cual tengo una columna de tipo text con un template, son montos totales. lo que deseo saber si se puede cambiar la suma total cuando cambio el text de mi gridview. la suma total lo almaceno en un texttoal q esta al final de formulario.
    gracias de antemano

    ResponderEliminar
  45. hola Eduardo

    algo que no has comentado es si este cambio solo aplica cuando entra en edicion la row del grid, o si ese textbox esta en el ItemTemplate siempre activo
    porque sino podrias aplicar

    [ASP.NET] - GridView sumar columnas con jquery

    saludos

    ResponderEliminar
  46. Hola Leandro,
    tengo un problema con un DropDownList que esta en un Grid, necesito sacar el valor que tiene el ddl y pasarlo como parametro a un sp, como hago para sacarlo si no me deja dirigirme al control como tal, Espero me puedas ayudar.

    Disculpa me confundi en el Post anterior! XD

    ResponderEliminar
  47. hola imrtnk

    deberias suar el FindControl() para acceder al control que esta en una row determinada

    lo primero que debes asegurar es que row, esto va a veriar segun que evento uses, pero basicamente el resto seri

    DropDownList ddl = row.FindControl("DropDownList1", DropDownList) as DropDownList;

    en este caso puse el ejemplo en c#, proque no indicaste en que lenguaje programas

    saludos

    ResponderEliminar
  48. Esta bien en C# es en el lenguaje que estoy trabjando, el problema es que no tengo un evento en especifico del grid, solo tengo estos dos eventos:
    1.- protected void grdResultadosBusqueda_RowDataBound(object sender, GridViewRowEventArgs e)

    2.- protected void grdPortal_SelectedIndexChanged(object sender, EventArgs e)

    crees que funcione con alguno de estos?

    Muchas Gracias por tu pronta respuesta.

    Saludos Cordiales.

    ResponderEliminar
  49. hola imrtnk

    puedes usar el SelectedIndexChanged para tomar la fila que se selecciona

    [ASP.NET][GridView] - Como seleccionar una fila

    en el link explico como podrias trabjar con la seleccion

    saludos

    ResponderEliminar
  50. Muchas Gracias Leandro,
    Me funciono perfecto!

    solo una duda mas si quiero sacar el RowIndex del Grid en el Evento del DDL como haria para ligarlo?
    Ya que cuando se cambia el valor en el DDL se ejecuta el evento ddl_SelectedIndexChanged pero RowIndex siempre aparece en -1
    hay alguna solucion para esto?

    O como Hago para pasar un numero de folio que viene desde la base de datos al atributo SelectedValue del DDL que esta dentro del mismo Grid?

    Muchas Gracias por tu ayuda!

    Eres un Master... XD

    ResponderEliminar
  51. hola imrtnk

    si desde un evento de un control quieres obtener el index de la row debes usar el NamingContainer

    [GridView] Eventos de controles contenidos en el Gridview


    saludos

    ResponderEliminar
  52. Muchas Gracias por tu ayuda Leandro!

    ya quedó con los ejemplos que me comentas.

    Saludos Cordiales!

    ResponderEliminar
  53. Hola Leandro,

    mi colsulta es similar a la respuesta que planteas:

    Tengo un GridView, y y DetailsView que muestro la fila seleccionada en el GridView.
    A la hora de editar el DetailView necesito que me aperezca el Dropdown de un campo que es de otra tabla relacionada.
    Esto se puede hacer?
    Saludos

    ResponderEliminar
  54. hola herculigan

    pero eso quiere decir que el DetailsView esta por fuera del gridview, o sea no es que editas al row del grid sino que seleccionas una row para editar

    GridView Examples for ASP.NET 2.0: Drilling Down into Detailed Data

    sino recuerdo mal el DetailsView tien un evento cuando se pone en edicion que podrias suar para cargar el combo

    saludos

    ResponderEliminar
  55. Maestro se pasa con sus rolas, Gracias.

    ResponderEliminar
  56. Tengo una consulta, al intentar actualizar la fila seleccionada en el Row_Updating, pude notar que en tiempo de ejecución, al precionar Actualizar no ingresa a este evento por lo tanto no puedo hacer la actualización, no se en que puedo estar fallando, porfavor alguna ayuda.... gracias!!!

    ResponderEliminar
  57. hola Sergio

    esta pregunta que realizo en el foro es tuya

    http://social.msdn.microsoft.com/Forums/es-ES/netfxwebes/thread/f925d6d6-5f17-4b65-ada8-9af7b1213505

    porque plantea un tema similar

    saludos

    ResponderEliminar
  58. Hola como estas? necesito una ayudita, necesito saber como poner este codigo GridViewChildren.DataBind( )
    para que al eliminar un dato del gridview se recargue automaticamente la pagina y no tenga que apretar F5

    Te paso las imagenes:

    gridview

    http://k45.kn3.net/0A8B86FCE.png

    Page_Load

    http://k35.kn3.net/02850AB9F.png


    Te comento que soy principiante

    Esta hecho con asp.net y vb.net


    Muchas gracias de antemano!

    Maga

    ResponderEliminar
  59. hola Magali

    lo que tendrias que hacer es despues de realziar la operacion de eliminar el item ejecutando el DELETE contra la db, simplemente recargar el grid completo

    o sea, seguramente usaste algun codigo (imagino es el metodo CheckAutenticationTicket()), en donde cargas el grid

    bueno luego de eliminar el registro deberias volver a invocar a ese metodo para refrecar el grid sin ese registro que acabas de eliminar

    saludos

    ResponderEliminar
  60. Hola mira tengo el siguiente problema. e hecho un seguimiento a mi codigo y me doy cuenta que el evento rowupdating se ejecuta 2 veces perdiendo los valores las variables. ¿cual sera el problema?

    aqui esta el codigo

    Protected Sub gvEditarUsuario_RowUpdating(sender As Object, e As GridViewUpdateEventArgs)

    Dim s As String = gvEditarUsuario.DataKeys(e.RowIndex).Value.ToString()
    Dim EmployeeID, Apellido As String

    EmployeeID = (DirectCast(gvEditarUsuario.Rows(e.RowIndex).FindControl("TextBox1"), TextBox).Text)
    Apellido = (DirectCast(gvEditarUsuario.Rows(e.RowIndex).FindControl("TextBox2"), TextBox).Text)
    Dim ID As New Guid(Membership.GetUser(EmployeeID).ProviderUserKey.ToString())


    SPIngresarUsuario("", "", Apellido, 87546295, ID, EmployeeID)
    gvEditarUsuario.EditIndex = -1
    BindData()
    End Sub

    ResponderEliminar
  61. hola Hector

    en principio no veo nada incorrecto en el codigo

    de casualidad uses el UpdatePanel? si es asi prueba quitarlo y ver si sigue el mismo problema

    el grid lo cargas en el Page_Load? si es asi recuerdas ponerlo dentro de

    If Not IsPostBack Then
    'aqui cargas el grid
    End Id

    saludos

    ResponderEliminar
  62. Hola como estas? Gracias por la ayuda anterior al final lo termine resolviendo aunque me costo.

    Tengo otra duda, yo estoy haciendo una web en asp.net y vb.net. El tema es el siguiente tengo que guardar los datos de un registro de empleados a otro es decir, cada empleado carga sus datos en un "Registro de empleados" cuando se cargan todos los datos que estos serian ej: (nombre, apellido, dni, edad, fecha de nac)cuando el empleado presiona el boton guardar se tienen que cargar en una table con labels todos cargados con los que puso el empleado. Antes estaba hecho con GridViews pero no lograba guardar la foto dentro del gridview entonces hice una tabla y que ahi se guarden todos los datos.


    Como deberia de hacer? Tengo que usar las bases de datos donde se guardaron esos datos y volcarlos a los labels? Como lo hago?

    Gracias de antemano

    Saludos!

    ResponderEliminar
  63. hola Magali

    no seria algo como esto

    [ASP.NET] GridView – Edición Empleados

    o sea en el grid puede mostrar la imagen de la entidad

    lo que no entendi es lo de los labels, porque no se supone que editas la entidad

    saludos

    ResponderEliminar
  64. Hola Leandro gracias por tu ayuda.

    tengo 2 tablas relacionadas entre sí: DEPARTAMENTOS Y EMPLEADOS. El objetivo de este proyecto es desplegar en un DropDownList todos los departamentos; de ahí, el usuario seleccionará uno, y el programa debe mostrar un listado usando un DataGrid o Gridview con los datos de todos los empleados que trabajan en ese departamento.

    ResponderEliminar
  65. hola Diego

    entonces en el combo que carga los departamentes asignale el evento SeelctedIndexChanged y la propiedad AutoPostBack = true

    con eso podrias tomar el SelectedValue del combo para usarlo de filtro que cargara el grid

    recuerda asignar el DataValueField del dropdownlist para que funcione el selectedvalue

    saludos

    ResponderEliminar
  66. que tal Leandro quisiera que me ayudaras, son muy pocos mis conocimientos en programacion, pero tengo que realizar un trabajo el cual consiste en que en un GridView se visualice una lista de empleados y exista un campo donde este un boton que al darle click guarde la hora del sistema en el campo de hora en el registro en el cual fue dado el click. Nose si me explique bien y si puedieras ayudarme a resolver mi cuestion
    de antemano gracias

    ResponderEliminar
  67. hola Jouse

    pero se supone que vas a grabar esa fecha directo en la db?

    porque se supone que podrias en el evento SelectedIndexChanged tomar el DataKey con el id de la entidad que se presiono el boton para poder realizar la actualizacion



    saludos

    ResponderEliminar
  68. si lo guardaria en la BD, el Grid me mostrara los empleados y al darle click al boton me guardara la hora de llegada de ese empleado,,me pudieras dar un pequeño ejemplo si no es mucha molestia porfavor

    te agradesco tu tiempo

    ResponderEliminar
  69. hola Jouse

    pero ese boton que hora registra a ese empleado ? seria la fecha y hora actual de ese momento

    porque podrias usar el evento SelectedIndexChanged ya que en el boton defines un CommandName = "Select"

    podrias tomar el id del empleado

    [ASP.NET][GridView] - Como seleccionar una fila

    entonces teniendo el id de la entidad, podrias realizar el insert o update pasando la DateTime.Now como parametro

    saludos

    ResponderEliminar
  70. si exactamente, toma la fecha y hora en el momento en que se da el click, muchas gracias Leandro, hare el intento con lo que acabas de mencionar, si se me presenta una dificultad o algo volvere para molestarte un poco jeje

    ResponderEliminar
  71. Saludos nuevamente Leandro muy acertada tu publicacion yo tengo problemas con esta linea que tu tienes
    DataRow row = DataAccess.GetUsuarioById(id);

    en mi caso intento poner
    DataRow row = clsTareaDiaria.ObtenerIdTarea(IdTarea, c_expediente);

    y pues esto me dice el siguiente error

    Error 2 Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Data.DataRow'

    te agradecere tu atencion a mi consulta

    ResponderEliminar
  72. hola Elsa

    pero el metodo ObtenerIdTarea() que tipo de dato esta retornando como respuesta ?

    porque por lo que parece deberias usar

    List<NombreClass> lista = clsTareaDiaria.ObtenerIdTarea(IdTarea, c_expediente);

    o sea lo asignas a una lista generica del tipo que devuelva

    saludos

    ResponderEliminar
  73. Si gracias Leandro logre encontrar mi error y si era ese el problema el tipo de dato que devolvia gracias de antemano aprovechando no tienes un link donde pueda encontrar como obtener la url de una pagina y enviarla por correo para que la consulten saludos

    ResponderEliminar
  74. Buenas tardes, muy agradecido por su blog, una consulta cada vez que debugeo se ejecuta 2 veces el RowEditing, el gridview esta dentro de un update panel, tambien eh colocado
    If Not IsPostBack Then
    Dim Filtro = ""
    CargarGvSuministros()
    end if ,
    A que se puede deber?

    ResponderEliminar
  75. hola Elsa

    no entendi lo que encontrar la url, mas que nada porque no quedo claro en que entorno tendrias re recuperar la url
    o en que accion se realizaria

    saludos

    ResponderEliminar
  76. hola Alex

    que raro que se ejecute dos, si quitas el UpdatePanel tambien sucede ?

    que pasas si usar el evento RowCommand y alli detectas el commandname que se ejecuta tambien ingresa dos veces alli?

    saludos

    ResponderEliminar
  77. Si lo siento mucho, bueno estoy en una aplicacion con WebForms ASP.NET c#, y tengo una pagina que se alimentara con parametros en su url y la debo de enviar por correo y desde la pagina que estoy debe generarse esa otra url y enviarla por correo no se si ahora me comprendes

    ResponderEliminar
  78. Buenos dias Leandor.
    Esta muy bueno tu codigo pero tengo un problema

    En el evento rowupdating hago esto:

    TextBox provincia = DgvInfo.Rows[e.RowIndex].Cells[2].Controls[0] as TextBox;
    string n = provincia.Text;

    pero no me trae lo que se a digitado en el texbox, me trae la informacion que estaba antes de editar. Segui tu codigo paso a paso, pero no logro capturar nuevo que se digita.
    Gracias!


    ResponderEliminar
  79. hola Johan

    pero puedes localizar el control TextBox cuando se lanza el evento ?

    si cargas el grid en el Page_Load has puesto el codigo dentro del

    if (!IsPostBack){
    //aqui cargas el grid
    }

    esto podria causar que se pierdan lo editado


    saludos

    ResponderEliminar
  80. Leandro.
    Gracias por tus esfuerzos publicando material importante.
    Hay algo que no comprendo en el ejemplo. El ejemplo considera que la tabla paises tiene como id su index. Cómo haría si el id es un campo que no necesariamente va a conincidir con el index? Intenté crear un nuevo SQLDATASOURCE para enlazar al DropDownList pero no me acepta. Se puede hacer eso o existe una alternativa mejor

    ResponderEliminar
  81. hola Jorge

    es que en realidad el index de los item de un combo no tienen porque coincidir con el id de la entidad que represente

    por eso se define el DataValueField, para poder usar el SelectedValue y recuperar el id de la entidad seleccionada

    no deberias usar nunca el index como representante del item que seleccionas, porque de seguro no coincide con el que tienes en la db


    saludos

    ResponderEliminar
  82. Buenas tardes Leandro, una consulta, si tengo 3 dropdownliss, uno con los dias del mes, otro con los meses y otro con los años, como hago para extraer la fecha de nacimiento, y que haga el calculo para que me traiga la edad en un texbox?

    ResponderEliminar
  83. hola Chester

    pero porque no usaste el control

    calendar ajax

    asi seleccionas una fecha directamente

    sino vas a tener que armarla

    DateTime fecha = new DateTime(Convert.ToInt32(ddlAño.SelectedValue),Convert.ToInt32(ddlMes.SelectedValue), Convert.ToInt32(ddlDia.SelectedValue));

    cada parte forma la fecha
    saludos

    ResponderEliminar
  84. hola leando que tal , fijate que tengo un proyecto en vb.net 2008 el cual utilizo un dropdownlist ya tengo la mayor parte del proyecto lo que ocupo es lo siguiente:

    de mi sql server quiero imprimir la tabla en un gridview pero al momento de agregar la sentencia en el datasource me pide un value ejem.

    idvisita=@idvisita el wizard me pide un value es ahi donde me quede parado te muestro el codigo

    LblProyecto.Text = GridDatos.Rows(e.NewSelectedIndex).Cells(1).Text()
    Session("IdSucursal") = GridDatos.Rows(e.NewSelectedIndex).Cells(4).Text()
    Session("Cadena") = GridDatos.Rows(e.NewSelectedIndex).Cells(3).Text()


    Dim fecha As String
    fecha = ""

    fecha = GridDatos.Rows(e.NewSelectedIndex).Cells(9).Text()

    If fecha = " " Then
    LblMensaje.Text = "Visita aun no tiene captura real"
    LblMensaje.Visible = True
    Exit Sub
    End If
    LblMensaje.Visible = False

    fecha = Format(CDate(GridDatos.Rows(e.NewSelectedIndex).Cells(9).Text()), "yyyy-MM-dd")
    fecha = fecha + " 00:00:00.000"
    Session("FechaVisita") = fecha

    If LblProyecto.Text = "AIPC" Then
    Server.Transfer("FrmAipc.aspx")
    End If
    If LblProyecto.Text = "El Jarro" Then
    Server.Transfer("Eljarro.aspx")
    End If
    If LblProyecto.Text = "Salsas Castillo" Then
    Server.Transfer("SalsasCastillo.aspx")
    End If
    If LblProyecto.Text = "InComm Tarjetas" Then
    Server.Transfer("FrmInCommTarjetas.aspx")

    End If
    lo que quiero que cuando en mi gridview seleccione el ultimo form que es el de incomm Tarjetas me aparesca el resultado del filtro de dropdownlist me podras ayudar ??

    ResponderEliminar
  85. Leandro,al cargar la grilla no aparece la columna dropdownlist.
    esta se llena en el evento rowbound?

    ResponderEliminar
  86. hola Hernan

    si te basas en el ejemplo deberias cargar los items del combo cuando pones en edicion la row del gridview

    o sea usarias el evento RowEditing, alli es donde cargarias el combo

    saludos

    ResponderEliminar
  87. como puedo cambiar los datos de un dropdownlist por medio de otro por Ej. Al seleccionar un pais en uno en el otro me muestre sus ciudades, etc..

    ResponderEliminar
  88. hola G

    pues la verdad no recomendaria anidar controles cuando editas directo en el gridview, cuando tiene logica compleja en la edicion es conveniente seleccionar la row y editar por fuera en controles simples


    saludos

    ResponderEliminar
  89. Hola
    estoy copiando el mismo código que tienes para poder guiarme en un ejercicio que estoy realizando pero en _RowUpdating me sale un error y me dice qeu en
    string nombre = text.Text;
    Object reference not set to an instance of an object.

    el codigo es igual no se por que me sale el error y no e podido solucionarlo

    int id = Convert.ToInt32(grUsuarios.DataKeys[e.RowIndex].Value);
    DropDownList combo = grUsuarios.Rows[e.RowIndex].FindControl("ddlPaises") as DropDownList;
    int pais = Convert.ToInt32(combo.SelectedValue);
    TextBox text = grUsuarios.Rows[e.RowIndex].Cells[1].Controls[0] as TextBox;
    string nombre = text.Text;
    DataAccess.UpdateUsuarios(id, nombre, pais);
    grUsuarios.EditIndex = -1;
    BindData();

    ResponderEliminar
  90. hola Nilson

    este error se produce porque seguramente la linea donde tomas el textbox, o sea

    TextBox text = grUsuarios.Rows[e.RowIndex].Cells[1].Controls[0] as TextBox;

    devuelve un null en la variable "text", se produce porque no puede encontrar o castear al textbox

    esa columna es del tipo BoundField ? porque si es un template podrias usar el FindControl()

    saludos

    ResponderEliminar
  91. Hola Lenadro Tutino, viendo tu código del evento RowEditing no entiendo como haces para que al darle clic en el botón Edit, te cargue en el Text con el valor que tenia la celda de forma automática, me refiero a la columna Nombre usuario, yo defino mi evento RowEditing pero no consigo que me cargue el texto de la celda en el Text para edición, ayuda please, muchas gracias!

    ResponderEliminar
  92. hola alan

    en el gridview esa columnas es un BoundField o es un Template ?
    lo pregunto porque cambia la forma en que lo haces

    si es un template deberias definir el <EditItemTemplate>
    alli pondrias el TextBox y en la propiedad Text harias lo mismo que uso en el Label, o sea

    <asp:TextBox ... Text='<%# Bind("descripcion") %>' />

    saludos

    ResponderEliminar
  93. NO, ese es el problema, no es ni uno ni otro, porque las columnas se crean de forma dinámica, usando un DataTable. Esto es así por la lógica del SW que estoy haciendo, no es fijo la cantidad de columnas, por lo que no se me ocurre otra cosa que usar un DataTable. La cuestión es que no logro capturar los Text en el RowEditing para que carguen los valores que tienen sus celdas respectivas...Tenes alguna sugerencia? Gracias!!

    ResponderEliminar
  94. hola alan

    si las columnas se crean de forma dinamica entonces son BoundField
    podrias hacer algo como ser

    string valorCell= ((TextBox)grdview1.Rows[e.RowIndex].Cells[1].Controls[0]).Text;

    ademas porque quieres tomarlo en el RowEditing, no sera en el RowUpdating que es donde se confirma el ingreso del dato por el usuario ?

    saludos

    ResponderEliminar
  95. No los encuentra si intento hacerlo de esa forma que decis, y lo quiero hacer en el RowEditing porque lo que quiero es que al momento de habilitarse los Text para edición, que aparezcan con el valor que tiene la respectiva celda, y no vació, no logro hacerlo, obvio que después vendría el RowUpdating como decís, pero antes quiero hacer eso, que los Text para edición no aparezcan en blanco, pero no se como hacerlo :(

    ResponderEliminar
  96. hola alan

    pero entonces usa lo que comente al principio:


    o sea no uses ningun evento, defines en el binding el valor que tomara el textbox

    saludos

    ResponderEliminar
  97. No se donde esta eso de binding, pero veo que te funciona porque creas las columnas en tiempo de diseño, yo creo las columnas en tiempo de ejecución, mediante programación, y las creo para el DataTable y no para la grilla como ya te comente antes. Por lo tanto no puedo hacer lo siguiente:



    que por el DataField debe ser que te funciona. Yo no lo puedo hacer porque la grilla no tiene nada, se crea todo a través del DataTable

    ResponderEliminar
  98. No salio el texto de lcodigo, aca va de nuevo:

    BoundField DataField="nombre" HeaderText="Nombre Usuario"

    ResponderEliminar
  99. hola alan

    la verdad no sabria decirte que esta pasando, siempre defini las columnas en tiempo de diseño y trabajo los datos de esta forma con BoundField o TemplateField

    de forma dinamica no se porque no se comporta de forma similar

    saludos

    ResponderEliminar
  100. Hola.. Buenas quisieras que me ayudes con algo estoy haciendo un carrito de compras online y quiero que al momento de dar clic en actualiza(gridview todo el proceso) me busque primero el stock del producto.. y si es mayor a lo q quiero aumentar entonces si actualizar.. si no no hace nada...
    Te agradeceria mucho tu respuesta :)

    ResponderEliminar
  101. hola Jennifer

    pero esto lo vas a implementar contra alguna db especifica? cual seria

    conoces sobre ado.net como para poder realizar una query que implemente la validacion
    sino entiendo mal deberias recuperar la entidad producto para poder conocer el stock que tiene

    saludos

    ResponderEliminar
  102. Muchas gracias de nuevo otro articulo que ke sirve de mucho.

    ResponderEliminar
  103. Hola Leandro, como pones el combo en la columna de los paises lo haces por htlm???

    ResponderEliminar
  104. hola Pedro

    si lo defino en el html en la columna del tipo <asp:TemplateField>

    Tutorial 12: Using TemplateFields in the GridView Control

    analiza el step 2

    saludos

    ResponderEliminar
  105. Leandro, veo que usas datatable, también se puede hacer con listas??

    ResponderEliminar
  106. hola Pedro

    como origen de datos para definir los items puedes usar listas o datatable

    saludos

    ResponderEliminar
  107. Leandro de esta manera veo que no funciona sin usar datarow

    public static Personal GetPersonalById(string id)
    {
    using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {
    cn.Open();
    using (SqlCommand cmd = cn.CreateCommand())
    {
    cmd.CommandText = "SELECT * FROM Personal WHERE = Personal_Id=@id";
    cmd.Parameters.AddWithValue("@id", id);
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
    if (reader.HasRows)
    {
    Personal _personal = new Personal();
    if (reader.Read())
    {
    _personal.Personal_Id = Convert.ToString(reader["Personal_Id"]);
    _personal.Nombre = Convert.ToString(reader["Nombre"]);
    _personal.Area_Id = Convert.ToString(reader["Area_Id"]);
    }
    return _personal;
    }
    else
    return null;
    }
    }
    }
    }

    ResponderEliminar
  108. hola Pedro

    no entendi, alli no usas ningun DataRow
    Esto que consultas tiene relacion con lo planteado en el foro

    http://social.msdn.microsoft.com/Forums/es-ES/013af98c-1481-465d-ad10-34818d44449e/gridview?forum=vcses

    saludos

    ResponderEliminar
  109. Una consulta, lo que pasa es que cuando le click la primera vez en la columna de editar no se me pone la caja de texto para la edición, pero ya la segunda vez, si aparece la caja de texto, alguna idea del porque?

    ResponderEliminar
  110. hola José

    la verdad muy raro, si pones un breakpoint en los eventos del grid puedes notar que pasa por estos?

    los datos los cargas en el Page_Load? si es asi pones dentro del
    if(!IsPostBack)
    porque sino se estara cargando en cada evento que se genere

    saludos

    ResponderEliminar
  111. Hola Leandro:

    Tengo un grid con las columnas: Maps, NoSuc y Direccion que se carga en un ModalPopupExtender desde un boton.
    En la columna Maps se carga un ImageButton con el metodo Onclick="addMarker_Click", quiero que al darle clic se cierre el Popup y me obtenga el valor de NoSuc de cada fila para recuperar en la siguiente funcion:

    public void addMarker_Click(object sender, ImageClickEventArgs e)
    {
    //Aqui recuperar el campo de la columna Sucursal
    int suc =

    }

    No se si me explique que es lo que quiero hacer.

    ResponderEliminar
  112. Cordial saludo Leandro.
    En primer lugar te agradezco por tus valiosos aportes.
    En segundo lugar quisiera preguntarte lo siguiente...
    Tengo un gridview con 6 columnas, de las cuales solo quiero que se habiliten en modo edición 3 al momento de hacer clic en el botón Editar. ¿Cómo puedo lograr esto?
    Gracias.

    ResponderEliminar
  113. hola Hanller

    podrias poner en ReadOnly = false solo las columnas que quieres editar

    o sea cuando presionas el boton editar tomas estas columnas y cambiarle el ReadOnly para que permitan su edicion

    eso si valida si el readonly del datagridview esta en false
    a las columnas accedes usando

    DatagridView1.Columns[0].ReadOnly = false;

    saludos

    ResponderEliminar
  114. Hola Leandro, buen día. Estoy intentando realizar una edición de diferentes campos de un GridView que obtiene los datos de un Sql Data Source. Dentro del grid inserté, en cada EditItemTemplate un DropDownList que también está enlazado a la base de datos, cada uno con un SqlDataSource respectivamente. El problema está en que al dar actualizar me muestra el siguiente error: "Los métodos de enlace de datos como Eval(), XPath() y Bind() sólo se pueden utilizar en el contexto de un control de enlace de datos.", presiento que es por lo que las consultas a la base de datos son de distintas tablas.

    Acá dejo los SqlDataSource del GridView y de uno de los edit template, espero puedas colaborarme. Saludos!


    DataSource GridView:

    asp:SqlDataSource ID="SDSTrabajadores" runat="server"
    ConnectionString="<%$ ConnectionStrings:ConexionGranjasOLEDB %>"
    ProviderName="<%$ ConnectionStrings:ConexionGranjasOLEDB.ProviderName %>"
    SelectCommand="select tr.id_trabajador, tr.fecha_registro, gr.id_granja, gr.nombre_granja, rt.id_rol, rt.nombre_roltr, tr.estado, decode (tr.estado, 'A' , 'ACTIVO', 'I' , 'INACTIVO') NOMBRE_ESTADO from tgr_trabajadorgranja tr, tgr_roltrabajador rt, tgr_granja gr where tr.id_rol = rt.id_rol and tr.id_granja = gr.id_granja"
    UpdateCommand="update tgr_trabajadorgranja set id_granja = :id_granja, id_rol = :id_rol, estado = :estado ">
    UpdateParameters>
    asp:Parameter Name="id_granja" />
    asp:Parameter Name="id_rol" />
    asp:Parameter Name="estado" />
    /UpdateParameters>
    /asp:SqlDataSource>

    EditItemTemplate:

    asp:TemplateField HeaderText="CARGO" SortExpression="NOMBRE_ROLTR">
    ItemTemplate>
    asp:Label ID="Label1" runat="server" Text='<%# Bind("NOMBRE_ROLTR") %>'>
    /ItemTemplate>
    EditItemTemplate>
    asp:DropDownList ID="DDLCargoTr" runat="server" DataSourceID="SDSCargo"
    DataTextField="ROL" SelectedValue='<%# Bind("ID_ROL") %>'
    AppendDataBoundItems="True" EnableViewState="False" DataValueField="CODIGOROL">
    /asp:DropDownList>
    asp:SqlDataSource ID="SDSCargo" runat="server"
    ConnectionString="<%$ ConnectionStrings:ConexionGranjasOLEDB %>"
    ProviderName="<%$ ConnectionStrings:ConexionGranjasOLEDB.ProviderName %>"
    SelectCommand="select id_rol CODIGOROL, nombre_roltr ROL from tgr_roltrabajador">
    /asp:SqlDataSource>
    /EditItemTemplate>
    /asp:TemplateField>

    ResponderEliminar
  115. hola Mile

    lo que entiendo esta generando problems es cuando haces

    SelectedValue='<%# Bind("ID_ROL") %>'

    la asignacion del valor deberia ir despues de cargar los items, quizas en algun evento DataBound
    de esta forma luego de que se carguen los datos asignarias la seleccion, pero todo junto asignar un valor y cargar los items no veo que se pueda

    saludos

    ResponderEliminar
  116. Buenos días Leandro. Hago lo que explicas en el post, pero cuando leo el selectedValue del ddl me trae siempre el primero. Estaré haciendo algo mal?

    ResponderEliminar
  117. hola Wilson

    en que evento cargas el dropdownlist, es en el Page_Load? porque si es asi recuerda usar el

    if(!IsPostBack){
    //aqui cargas el combo
    }

    sino haces eso en cada accion se recargara perdiendo la seleccion

    saludos

    ResponderEliminar
  118. Hola Leandro, Estoy cargando el combo en el RowEditing, como lo muestras en el post. Estoy usando versión 4.5 del FrameWork y el VS2012. Eso afecta en algo? Descargué el ejemplo tuyo y funciona perfecto, pero cuando lo hago en mi proyecto, no.

    protected void grv1_RowEditing(object sender, GridViewEditEventArgs e)
    {
    grv1.EditIndex = e.NewEditIndex;
    CargarDatos();

    DropDownList combo = grv1.Rows[e.NewEditIndex].FindControl("ddlEdit") as DropDownList;

    if (combo != null)
    {
    combo.DataSource = model.spObtenerHoras();
    combo.DataTextField = "DescHora";
    combo.DataValueField = "IdHora";
    DataBind();
    }
    }

    ResponderEliminar
  119. hola Wilson

    porque veo que usas un DataBind(); ? no deberia ser:

    combo.DataBind();


    saludos

    ResponderEliminar
  120. hola leo disculpa como puedo llamar datos de mi base de datos a mi combo-box dentro de mi grid

    ResponderEliminar
  121. hola fausto

    depende si el combo esta en un template que se activa al poner la row en edicion o no

    si esta en un template simple podrias usar el evento RowDataBound y con el FindControl() ubicar el combo y asignar el DataSource

    sino haces lo mismo pero en el evento que pone en edicion la row del grid

    saludos

    ResponderEliminar
  122. gracias leo
    me visualiza la información de mi tabla en el DROPDOWNLIST dentro de mi grid pero cuando actualizo y cambio de valores no me los cambia en mi base de datos
    este es mi codigo









    ResponderEliminar
  123. Leandro, el código en mi proyecto de C# da error en el objeto DataAccess. Dice "El nombre DataAccess no existe en el contexto actual". ¿Alguna sugerencia?

    ResponderEliminar
  124. hola Claudio

    validaste si los proyectos estan referenciados ?

    usa la opcion de "Add Reference"

    saludos

    ResponderEliminar
  125. Leandro, mi error, soy novato en todo esto.

    Estuve viéndolo y mi error fue no incluir la clase que tiene.

    Pero, te hago la pregunta directa, tengo una tabla, esa tabla la muestro con un griedview, hay datos que apuntan a otras tablas y datos fijos.

    Necesito, para editar el gridview, que se pueda realizar mediante DropDownList, tanto las columnas que esán relacionadas con otras tablas, como las que son fijas.

    Para el caso que son fijas, tienen alternativa "SI, "NO". Por lo tanto, he investigado cómo crear un DropDownList con datos fijos que sea seleccionable en el modo editar del gridview.

    Es en C#.

    De antemano, muchas gracias.

    ResponderEliminar
  126. Buen día Leandro oye estaba checando el código y al final vi los links de descarga pero ya no estan disponibles :( no se si podrías habilitar de nuevo :)
    de antemano muchas gracias!!!

    PD. Gracias por todas tus publicaciones no sabes como me han ayudado y orientado eres un gran instructor :3

    ResponderEliminar
  127. jejeje ya no importa :D ya logramos aplicarlo :3 gracias por el codigo ;)

    ResponderEliminar
  128. hola Claudio

    pero para definir un combo con datos fijos solo defines en el EditeTemplate del grid el DropDownList con los ListItem con esa informacion

    como ser

    <asp:DropDownList id="DropDownList1"
    runat="server">
    <asp:ListItem Value="0">No</asp:ListItem>
    <asp:ListItem Value="1">Si</asp:ListItem>
    </asp:DropDownList>


    saludos

    ResponderEliminar
  129. Muchas gracias por la respuesta Leandro. Pude resolver antes el problema exactamente con la explicación que das. Era problema de parchar un código anteriormente hecho por otra persona. Me salió mejor crearlo nuevamente con lo recabado en internet.

    ResponderEliminar
  130. Buen día Leandro.
    Tengo una consulta, dispongo del siguiente GridView con la siguiente información. Hay una forma de obtener el elemento seleccionado de cada DropDownList del GridView dentro del evento de un Button sin tener que utilizar el evento del GridView (RowEditing)?
    1 XXX ABCDE DropDownList 1
    2 XXX VWXYZ DropDownList 2
    3 XXX ASDFG DropDownList 3

    Saludos...

    ResponderEliminar
  131. Mil Gracias Leandro, la explicación esta excelente y el ejemplo corre de maravilla!!!

    ResponderEliminar
  132. Hola,Buenos días Leandro, me guie por el código que muestras, pero al verlo, no entiendo la siguiente línea de código: “DataRow row = DataAccess.GetUsuarioById(id);” y mas abajo viene esta otra línea “combo.SelectedValue = Convert.ToString(row["pais"]);”

    En mi código, lo hice así, pero no me sale la información de mis ddl, ni se actualiza. Espero tu ayuda, de antemano muchas gracias.

    protected void gvDir_RowEditing(object sender, GridViewEditEventArgs e)
    {
    gvDir.EditIndex = e.NewEditIndex;
    int DIR = Convert.ToInt32(gvDir.DataKeys[e.NewEditIndex].Value);

    DropDownList combo = gvDir.Rows[e.NewEditIndex].FindControl("ddlOrganismo") as DropDownList;
    if (combo != null)
    {
    combo.DataSource = TrtpCatOrganismos.Search();
    combo.DataTextField = "Descripcion";
    combo.DataValueField = "Organismo";
    combo.DataBind();
    }
    combo.SelectedValue = Convert.ToString("Organismo");
    LlenaGvDir();
    }

    ResponderEliminar
  133. hola Nayeli

    el metodo DataAccess.GetUsuarioById() es parte de la capa de datos, esto permite encapsular el acceso a datos.

    Esa funcionalidad retorna una row de DataRow y de esta obtienes el valor de un campo que asignas al valor del combo para seleccionarlo

    saludos

    ResponderEliminar
  134. hola Leandro, tengo un problema al actualizar mi registro, al dar click en actualizar, me salen los textbox para realizarlo, pero al guardar no me establece el cambio, estoy usando un Dataset.
    ¿Cómo podria actualizar mi registro?Mi codigo del updating es:


    protected void gvDir_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
    int DIR = Convert.ToInt32(gvDir.DataKeys[e.RowIndex].Value);


    TextBox txtDir = gvDir.Rows[e.RowIndex].Cells[2].Controls[0] as TextBox;
    string descripcion = txtDir.Text;

    TextBox txtCall = gvDir.Rows[e.RowIndex].Cells[3].Controls[0] as TextBox;
    string Calle = txtCall.Text;

    TextBox txtCol = gvDir.Rows[e.RowIndex].Cells[4].Controls[0] as TextBox;
    string Colonia = txtCall.Text;

    TextBox txtcp = gvDir.Rows[e.RowIndex].Cells[5].Controls[0] as TextBox;
    string CP = txtcp.Text;

    TextBox txtCiudad = gvDir.Rows[e.RowIndex].Cells[6].Controls[0] as TextBox;
    string Ciudad = txtCiudad.Text;

    DropDownList combo = gvDir.Rows[e.RowIndex].FindControl("ddlOrganismos") as DropDownList;
    int organismo = Convert.ToInt32(combo.SelectedValue);

    DropDownList combo2 = gvDir.Rows[e.RowIndex].FindControl("ddlEstados") as DropDownList;
    int estado = Convert.ToInt32(combo2.SelectedValue);

    TextBox txtUsuAlta = gvDir.Rows[e.RowIndex].Cells[9].Controls[0] as TextBox;
    string UsuAlta = txtUsuAlta.Text;


    gvDir.EditIndex = -3;
    LlenaGvDir();


    Espero me puedas ayudar, muchas gracias.

    ResponderEliminar
  135. Leandro buenas tardes,

    siempre con molestis pero agradeciendo su colaboración.

    Tengo el siguiente problema:

    estoy aprendiendo de una forma obligada el funcionamiento de NHibernate, para lo cual defini mis archivos xml y mis clases, se me presento un problema con una tabla que tenia dos campos como primary key, para lo cual aprendi a usar composite-id hasta este punto me ha funcionado bien por que ya guardo roles sin problema.

    cunado creo un gridview y genero de forma manual las columnas lleno una columna con una propiedad que se llama "RolPK.idRol" que es una propiedad de la clase que cree para el primary key y que esta contenida en la clase rol, en el gridview me muestra datos correctamente, pero si quiero definir esa misma propiedad como el DataFieldValue para un dropdownlist me genera el mensaje

    "DataBinding: 'Entidades.Entidades.Rol' no contiene una propiedad con el nombre 'RolPK.idRol'.", ya he mirado muchas formas y nada la duda es que puedo hacer para solucionarlo y por que si funciona en gridview y no en el dropdownlist?

    Gracias

    ResponderEliminar
  136. Leandro buenas tardes,

    siempre con molestis pero agradeciendo su colaboración.

    Tengo el siguiente problema:

    estoy aprendiendo de una forma obligada el funcionamiento de NHibernate, para lo cual defini mis archivos xml y mis clases, se me presento un problema con una tabla que tenia dos campos como primary key, para lo cual aprendi a usar composite-id hasta este punto me ha funcionado bien por que ya guardo roles sin problema.

    cunado creo un gridview y genero de forma manual las columnas lleno una columna con una propiedad que se llama "RolPK.idRol" que es una propiedad de la clase que cree para el primary key y que esta contenida en la clase rol, en el gridview me muestra datos correctamente, pero si quiero definir esa misma propiedad como el DataFieldValue para un dropdownlist me genera el mensaje

    "DataBinding: 'Entidades.Entidades.Rol' no contiene una propiedad con el nombre 'RolPK.idRol'.", ya he mirado muchas formas y nada la duda es que puedo hacer para solucionarlo y por que si funciona en gridview y no en el dropdownlist?

    Gracias

    ResponderEliminar
  137. Hola Leandro, Gusto en saludarte. Quisiera acudir a ti con la sgte consulta en relacion a ASP.NET (Visual).

    Tengo en un gridview1 que carga una dato de sql server (rut). A este campo(en el gridview) le he agregado una columna template que contiene un boton. Necesito:

    Al presionar el boton de la linea, me visualice un reporte en crystalreport en modo popup, con la información que esta almacenada en la tabla sql (nombre, apellido, edad, apellido, ciudad), relacionada al RUT.

    Podrías ayudarme con esto?

    en ASP CODE TENGO:

    asp:TemplateField HeaderText="VER OC" ShowHeader="False">






    El código Visual no se como va.


    Desde ya muchas gracias.

    Quedo atento.

    ResponderEliminar
  138. hola Claudio

    pero no necesitas un boton que envie una accion al servidor para mostrar un popup, podrias poner un simple link o boton de html que lance un javascript que defina un window.open()

    How to open a new window from GridView using JavaScript? - Asp.Net C# and Vb.Net

    solo que en tu caso enviarias el id de la entidad en la url que abres en el popup para enviarlo por parametro al reporte y muestre los datos de esa entidad

    saludos

    ResponderEliminar
  139. HOLA LEANDRO, MUCHAS GRACIAS, ME HA FUNCIONADO PERFECTO, ERES UN MAESTRO.

    AHORA, OTRA CONSULTA.

    Necesito subir archivos PDF desde la web (cargar archivos PDF) y que cambie el nombre del archivo original por uno que relacione el nª de una factura. Por ejemplo, estoy creando una orden de compra con Nª50 y debo cargar la cotización previa, relacionada con esa orden de compra que estoy creando. el nuevo nombre del archivo al subir debería cambiarse de acuerdo a la numeración de la orden de compra, para poder buscar el PDF mas tarde, pero debiera ser automático al momento de carga o al final (al momento de guardar los datos en BD). Paralelo a esto, debiera guardar la ruta en base de datos y después, a través de un botón en una grilla, poder visualizar la cotización de acuerdo al Nª de orden de compra que estoy consultando en la linea de la grilla.

    Crees que puedas ayudarme con esto?

    Desarrollo en ambiente ASP.NET (VISUAL BASIC)


    Muchas gracias nuevamente.

    ResponderEliminar
  140. hola Claudio

    son varios los puntos que planteas en la preguta, va a llevar un tiempo responderlos a todos

    para cambiar el nombre del archivo que subes solo lo defines cuando usas el FileUpload.SaveAs() al grabar indicas la carpeta y el nombre que tendra, no uses el FileName que el fileupload menciona

    si quieres podrias plantear el tema en el foro de asp.net
    asp.net foro
    alli va a ser mas simple de escribir codigo

    saludos

    ResponderEliminar
  141. Todos los problemas que he tenido te encuentro preguntando lo mismo en MSD jaja Saludos

    ResponderEliminar
  142. En aplicacion windowsform tengo un gridcontrol devexpress algunas tablas tienen 2 primary key, cuando las carga el control da error de claves primary key por no ser unicas, pero en las tablas no estan repetidas, con el manager sql, van correctamente, cual es el problema?, gracias.

    ResponderEliminar