none
Manejo de registros de los Datagrid en wpf? RRS feed

  • Pregunta

  • Hola amigos, estoy utilizando un datagrid del vs 2010 beta 2 y hay una cosa que estoy haciendo mal, les comento, el compañero del foro David Gonzàlez me envio un codigo para recoger los datos del listview y tambien del lostfocus, lo adapte y todo sin problemas, ahora lo estoy reutilizando para el datagrid y tambien recogo los datos pero al tener que pulsar doubleclick para editar ya se pierde el foco solo

    1 - Puede configurarse el datagrid para que con ponerse encima del row pueda ser editado sin double click y no solamente con el raton, he visto la propiedad beginedit() pero solo lo hace al cambiar de fila y el primer campo solamente, asi no tendria problemas con el lostfocus y al salir del campo que este editando si funcionara lostfocus correctamente.

    2 - Existe algun metodo que sea llamado cuando yo inserto algo en algun texto de la linea inferior del datagrid, me refiero al de insertar una nueva fila, si es llamado por algun metodo o como regoco esos datos insertados en esa nueva fila, si podeis ver ahora lo aho con selectedcellchanged y si el id que recogo es null creo una fila, pero me gustaria saber si existe un metodo mejor.

    3 - Es posible actualizar u datagrid sin tener que instanciarlo de nuevo?, me refiero si al crear la nueva fila puede refrescarse automaticamente sin tener que cargarlo todo de nuevo.

    4 - Como se puede validar los parametros insertardos en cada row del datagrid automaticamente, me refiero si es posible en un campo int no dejar escribir cadena de caracteres.

    5 - Como se puede recoger las excepciones en una celda entera, con selectedcellchanged?, existe alguna forma de recoger un solo row, ya he comentado antes que el lostfocus no me funciona bien, ya que lo que yo escriba dentro del row ya no pierde el foco al perderlo anteiormente.

    6 - Se puede eliminar una celda entera y que esta desaparezca automaticamente del datagrid?

    7- Como puedo hacer que cuando se pulse enter avance un campo y no una fila entera?

    xaml :

     

    <
    UserControl
     x:Class
    =
    "
    Profesores.datos
    "
    
    xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
    xmlns:x = " http://schemas.microsoft.com/winfx/2006/xaml "
    xmlns:mc = " http://schemas.openxmlformats.org/markup-compatibility/2006 "
    xmlns:d = " http://schemas.microsoft.com/expression/blend/2008 "
    mc:Ignorable = " d "
    d:DesignHeight = " 300 " d:DesignWidth = " 500 " >
    < Grid >
    < DataGrid SelectionUnit = " FullRow " SelectedCellsChanged = " dataGrid1_SelectedCellsChanged " Height = " 211 " HorizontalAlignment = " Left " Margin = " 28,69,0,0 " Name = " dataGrid1 " VerticalAlignment = " Top " Width = " 443 " CanUserResizeColumns = " False " CanUserResizeRows = " False " LostFocus = " dataGrid1_LostFocus " />
    </ Grid >
    </ UserControl >

    c#

     

    using
     System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Data;
    using System.Data.SqlClient;


    namespace Profesores
    {
    /// <summary>
    /// Interaction logic for datos.xaml
    /// </summary>
    public partial class datos : UserControl
    {
    public datos()
    {
    InitializeComponent();
    Modelos.Clase_Usuarios controladorVista = new Modelos.Clase_Usuarios();
    controladorVista.mostrarUsuarios();
    SqlDataAdapter adaptador = new SqlDataAdapter();
    adaptador = controladorVista.getconsultaUsuariosDA();
    DataSet datos = new DataSet();
    adaptador.Fill(datos, "Usuarios" );
    dataGrid1.ItemsSource = datos.Tables[0].DefaultView;
    controladorVista.cerrarConexion();
    }

    private void dataGrid1_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
    {

    DataRowView drv = dataGrid1.CurrentCell.Item as DataRowView;
    if (drv!= null )
    {
    string id = drv.Row[0].ToString();
    string usuario = drv.Row[1].ToString();
    string password = drv.Row[2].ToString();
    string nombre = drv.Row[3].ToString();
    string apellidos = drv.Row[3].ToString();
    Modelos.Clase_Usuarios usuarios = new Modelos.Clase_Usuarios();
    //usuarios.setId(null); Es autoincrementable
    usuarios.setNombre(nombre);
    usuarios.setUsuario(usuario);
    usuarios.setPassword(password);
    usuarios.setApellidos(apellidos);
    usuarios.actualizarUsuario();
    controladorVista.cerrarConexion();

    }
    else
    {
    Modelos.Clase_Usuarios usuarios = new Modelos.Clase_Usuarios();
    //usuarios.setId(null); Es autoincrementable
    usuarios.setNombre("inserte Nombre" );
    usuarios.setUsuario("inserte Usuario" );
    usuarios.setPassword("inserte Password" );
    usuarios.setApellidos("inserte Apellidos" );
    usuarios.insertarUsuario();
    }


    }

    private void dataGrid1_LostFocus(object sender, RoutedEventArgs e)
    {

    DataRowView drv = dataGrid1.CurrentCell.Item as DataRowView;
    if (drv != null )
    {
    string id = drv.Row[0].ToString();
    string usuario = drv.Row[1].ToString();
    string password = drv.Row[2].ToString();
    string nombre = drv.Row[3].ToString();
    string apellidos = drv.Row[3].ToString();
    Modelos.Clase_Usuarios usuarios = new Modelos.Clase_Usuarios();
    //usuarios.setId(null); Es autoincrementable
    usuarios.setNombre(nombre);
    usuarios.setUsuario(usuario);
    usuarios.setPassword(password);
    usuarios.setApellidos(apellidos);
    usuarios.actualizarUsuario();


    }
    else
    {
    Modelos.Clase_Usuarios usuarios = new Modelos.Clase_Usuarios();
    //usuarios.setId(null); Es autoincrementable
    usuarios.setNombre("inserte Nombre" );
    usuarios.setUsuario("inserte Usuario" );
    usuarios.setPassword("inserte Password" );
    usuarios.setApellidos("inserte Apellidos" );
    usuarios.insertarUsuario();
    }
    }


    private System.Data.DataRowView getListItem(FrameworkElement _element)
    {
    if (_element != null )
    {
    // obtener el item de la lista
    DataGridRow item = (DataGridRow)dataGrid1.ContainerFromElement(_element);
    if (item != null )
    {
    // obtener el indice del item de la lista
    int index = dataGrid1.ItemContainerGenerator.IndexFromContainer(item);
    // retornar la vista de la fila con los datos
    return (System.Data.DataRowView)dataGrid1.Items[index];
    }
    }

    // si no se encuentra se retorna null
    return null ;
    }



    }
    }


    Muchas gracias
    domingo, 28 de marzo de 2010 9:04

Respuestas

  • Hola WpfSoft.

    Para que te funcionasen los metodos y para obtener actualizados los elementos tienes que implementar la plantilla de edicion, en los ejemplos que has puesto solo tienes la plantilla normal (de lectura), se deben implementar las 2, algo como:

     

                    <DataGridTemplateColumn Header="nombre" Width="70">
                        <!-- plantilla para el modo lectura del grid -->
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate x:Name="prueba2">
                                <TextBlock Name="name" Text="{Binding Mode=TwoWay, Path=name}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                        <!-- plantilla para el modo edicion del grid -->
                        <DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate x:Name="prueba">
                                <TextBox Name="nameEdit" Text="{Binding Mode=TwoWay, Path=name}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellEditingTemplate>
                    </DataGridTemplateColumn>

     

    de esta forma, cuando el grid entre en modo edicion, mostrara el control de la plantilla de edicion.

    No obstante, como veo que estas poniendo TextBox, no hace falta que uses la plantilla de edicion ya que un textBox siempre se puede editar.

    en el otro post te he puesto una forma de implementar lo que buscas:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/b96ff232-48bf-42b9-a6df-dd94b79bdb37

     

    En cuanto a la creacion dinamica de controles, se puede realizar y basandonos en lo que ya tenemos de la siguiente forma:

    en lugar de implementar los TextBox en las plantillas, se inserta un contenedor para poder insertar dentro lo que se desee cuando se va cargando, por ejemplo algo como esto:

     

                    <DataGridTemplateColumn Header="nombre" Width="70">
                        <!-- plantilla para el modo edicion del grid -->
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Loaded="nameEdit_Loaded">
                                </StackPanel>
                            </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

     

    De esta forma tenemos un panel para insertar lo que deseemos, de modo que en el evento 'Loaded' podemos hacer algo como esto:

     

            private void nameEdit_Loaded(object sender, RoutedEventArgs e)
            {
                // obtener el panel de la plantilla
                StackPanel panel = (StackPanel)e.OriginalSource;
    
                // guardar referencia al panel correspondiente
                m_list.Add(panel);
    
                // en los impares se inserta un TextBox
                if (m_list.Count % 2 == 0)
                {
                    // crear el TextBox
                    TextBox text = new TextBox();
                    // crear el binding para el textbox
                    text.SetBinding(TextBox.TextProperty, "name");
                    text.KeyDown += new KeyEventHandler(pulsarTeclaEnter);
    
                    // añadir el control al contenedor de la plantilla
                    panel.Children.Add(text);
                }
                // en los pares se inserta un TextBlock
                else
                {
                    // crear el TextBox
                    TextBlock text = new TextBlock();
                    // crear el binding para el textbox
                    text.SetBinding(TextBlock.TextProperty, "surname");
    
                    // añadir el control al contenedor de la plantilla
                    panel.Children.Add(text);
                }
    
            }

     

    en este ejemplo inserto un TexBlock en las columnas impares y un TextBox en las pares (esto se debe hacer como se desee, tan solo es un ejemplo para ver como insertar un control en una celda concreta) de esta forma, cada celda puede tener un control diferente.

    Los contenedores se van almacenando en una lista generica de tipo 'FrameworkElement' como esta:

     

    private List<FrameworkElement> m_list = new List<FrameworkElement>();

     

    de forma que puedas acceder luego a los controles como se desee.

    En el TextBox he implementado el evento 'KeyDown' como en los otros ejemplos tuyos, de forma que se pueda implementar este evento para pasar el foco de uno a otro como en el link que he puesto antes.

    Si tienes alguna duda comentamelo.

     

    Saludos
    David González
    • Marcado como respuesta WpfSoft domingo, 4 de abril de 2010 9:30
    sábado, 3 de abril de 2010 22:29

Todas las respuestas

  • Hola WpfSoft.

    Como es un poco amplios los puntos y haria falta un articulo entero, intentare darte algunas pistas para ir viendo los puntos sobre la marcha.

    debido a las plantillas y estilos WPF tiene muchos mecanismos para solucionar los puntos, asi que te comento una forma para realizarlo que te permita solucionarlos casi todos. Esto es mediante las plantillas.

    Como quieres modificar el comportamiento y posiblemente la apariencia al gusto, lo ideal es crearte una plantilla para modificar grid de modo que tengas un mayor control sobre los elementos del mismo.

    1.- partiremos realizando una plantilla para las columnas, de forma que definamos los controles normales y los de edicion del grid, de forma parecida a como se realiza en ASP.NET.

    para el ejemplo estoy usando una tabla que contiene 3 columnas (id, name, surname) que deberas de modificar en consecuencia.

    codigo xaml:

     

    <DataGrid AutoGenerateColumns="false" Height="251" HorizontalAlignment="Left" 
              Margin="12,12,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="479" AlternatingRowBackground="LightSteelBlue" CellEditEnding="dataGrid1_CellEditEnding">
        
        <DataGrid.Columns>
        <!-- columna ID -->
        <DataGridTemplateColumn Header="id">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding id}" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>                        
                    <TextBox Text="{Binding id, Mode=TwoWay}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>                
        </DataGridTemplateColumn>
    
        <!-- columna name -->
        <DataGridTemplateColumn Header="name">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                        <TextBlock Text="{Binding name}" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding name, Mode=TwoWay}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    
        <!-- columna surname -->
        <DataGridTemplateColumn Header="surname">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                        <TextBlock Text="{Binding surname}" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding surname, Mode=TwoWay}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
            
        </DataGrid.Columns>
    </DataGrid>

     

    En este codigo puedes observar que he creado un grid redefiniendo la plantilla para las columnas, cellTemplate tiene las columnas en modo normal, mientras que CellEditingTemplate son las que se mostraran en modo de edicion.

    Se puede observar que para la edicion he establecido un TextBox para insertar datos, mientras que en las columnas normales tiene un TextBlock para mostrarlos (estos pueden ser otros controles si lo deseas).

    El TextBlock tiene un evento 'MouseLeftButtonUp' que sera lanzado al pulsar y liberar el boton del raton, el cual llamara al siguiente evento en el codigo .cs

     

    private void TextBlock_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        dataGrid1.BeginEdit();
    }

     

    Esto lo que hace es que establecera la columna seleccionada en modo de edicion, de forma que se muestre el modo de edicion y puedas modificar la celda.

     

    2.- el metodo es 'CellEditEnding' (que esta puesto en el codigo xaml anterior, este se puede controlar mediante el siguiente evento:

     

            private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                // controlar evento
            }   

     

     

    3.- Este punto, no se a que te refieres, pero es relativo a la forma de enlazar los datos, en el ejemplo que expongo, los TextBox tienen un binding bidireccional (Mode=TwoWay) de forma que lo que se inserte en el sera guardado en la fuente de datos, aunque por defecto hay que realizarlo explicitamente y depende de donde y como estas enlazando los datos.

    te paso un link con algunos ejemplos sobre el tema y si necesitas ayuda concreta me lo comentas:

    http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx

     

    4.- En este punto, como hemos creado una plantilla, se puede crear un evento en los TextBox para previsualizar la tecla pulsada de igual forma que haciamos en el post:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/be0e1dc0-5a67-482c-9f8a-2b38cb7119ee

    pero en lugar de detectar la tecla 'Intro', se deben descartar todas las teclas que no quieras que se inserten.

    Por defecto el datagrid tiene validador, de forma que en una columna de tipo int no puedes insertar caracteres por que no te deja terminarla de editar, pero si lo que quieres es que no se pueda escribir, tienes que hacer algo como lo que te he comentado o crearte una mascara de edicion.

     

    5.- en esta no se a que te refieres con excepciones, si son excepciones de insercion de datos el punto 4 lo soluciona.

     

    6.- Si que se puede mediante las plantillas, pero esto si que requiere que se tenga que actualizar todo el grid, si estas interesado en realizarlo lo podemos mirar cuando lo vayas a implementar.

    7.- esto no lo he comprobado, pero como tenemos la plantilla definida, puedes capturar la tecla en el evento del punto 4 y mover el foco a la siguiente celda.

     

    En un principio he explicado un poco los pasos por encima para que te hagas una idea de como lo implementaria yo de forma relativamente sencilla, pero como te iran surgiendo dudas y problemas ya me los comentaras a ver si te puedo ayudar.

     


    Saludos
    David González
    martes, 30 de marzo de 2010 8:20
  • Hola David, muchas gracias como siempre, te comento, que metodo del datagrid recoge cuando pulso en la fila vacia de abajo, mi objetivo es que cuando se pulse en la fila vacia de abajo automaticamente cree un nuevo registro en la ddbb y rellene esta fila con uno datos predeterminados, tanto en la ddbb cono en la fila y que ademas cree una nueva fila debajo en blanco, te explico los pasos.

    1 - Pulso en la nueva fila de abajo, supongo que detectare que el datarow view es null y creo un nuevo registro en la ddbb, tomamos como ejemplo que el id del registro es el 243 y al ser autoincrementable se creara sola, los demas datos en consecuencia como los inserto con unos valores predeterminados, por ejemplo usuario = USUARIO , nombre = NOMBRE y password = PASSWORD.

    2 - Es este punto tengo una duda, ¿ como puedo insertar esos valores en la fila que he pulsado anteriormente y que era una nueva ?,

    3 - Ademas de lo anterior se debe de crear una nueva fila debajo del todo en blanco para poder seguir insertando nuevos registros, este es el codigo que utilizo, no se si sera el mas indicado, lo que hago es insertar un nuevo registro en la ddbb y recogo el id y este ultimo lo muestro de esta forma para crear un nuevo row.

    DataRowView nuevoRow = ((DataView)dataGrid1.ItemsSource).AddNew();
    nuevoRow[0] = ultimaID ;
    nuevoRow[1] = usuario;
    nuevoRow[2] = password;
    nuevoRow[3] = nombre;
    nuevoRow[4] = apellidos;

    4 - Supongo David que existira una manera de simular la columna primera de un datagrid de winforms, la que lleva los iconos de creacion de filas, dime si me equivoco, creo una nueva columna anterior a la del id y pongo un texto como > que se repetira tantas veces como filas, ahora mi duda, como diferenciar las filas con datos de la ultima para insertar registros, lo ideal es que esta en vez de mostrar > mostrar un * tal como lo hace winforms.

    5 - Como prodiamos hacer para que solo se inserte una nueva fila en blanco debajo de las demas cuando terminemos de completar el nuevo registro?, si te das cuenta David si tu pulsas en la nueva fila y crea un registro y dejas los demas en blanco y pulsa en cualquiera otra fila se crea una nueva, se que lo controlaremos mediante validaciones, pero me gustaria saber si existe un comando para añadir las nuevas filas desde el codigo cuando yo quiera, se que con el comando CanUserCanRows en falso ya no lo crea el usuario, pero me gustaria poder crearlos yo desde el codigo.

    6 - Como recojo el datos actual que ha cambiado en la celda?, el codigo que he creado coje todo el row entero pero sin actualizar, con el tengo ya la id,  he probado con que me enviaste en un post anterior para recogerlos desde el listview pero al no existir el originalsource no puedo saber cual es el valor actual del textbox, te paso el codigo que recoge toda la fila cuando se termina de editar una celda.

     

            private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                
                DataRowView drv = e.Row.Item as DataRowView;
                int idR = (int)drv.Row[0];
                string usuarioR = drv.Row[1].ToString();
                string passwordR = drv.Row[2].ToString();
                string nombreR = drv.Row[3].ToString();
                string apellidosR = drv.Row[4].ToString();
    
                MessageBox.Show("ID : " + idR.ToString() + " USUARIO : " 
    + usuarioR + " PASSWORD : " + passwordR + " NOMBRE : " + nombreR + " 
    APELLIDOS : " + apellidosR);
    
            }

     

    David tengo otra duda que se qu ee suna tonteria pero lo he intentado y no me sale el resultado esperado, te comento, como puedo mostrar diferentes datatemplates u objetos de estos pasandole un valor, por ejemplo, si tengo un valor 1 quiero que me muestre una texbox y si el valor es 0 quiero que me muestre un textblock, el objetivo es que dependiendo de los valores que recogo de la ddbb me carge diferentes componentes en la vista, ya sean textblock, images.

    El punto 6 del comentario anterior ( el del inicio del post ) me interesa mucho, ya que si elimino una fila quiero que se elimine del datagrid, supongo que si guardo un parametro con la id anterior al cargar el datagrid puedo hacer que el foco este en esa fila al recargar el datagrid no?.

    Otra cosa David, tu sabes si el datagrid del vs 2010 al ser este una beta puede contener bugs?, es que utilizandolo me di cuenta que si pongo el lostfocus activado y pulso en la ultima fila y lanzo el evento messagebox.shox(valor) no me seguia añadiendo nuevas filas debajo de estas, seguramente es un fallo mio de implementacion, cuando salga el vs 2010 en abril el componente datagrid sera una beta o no?, solo por curiosidad.

    Espero tus respuestas com siempre y muchisimas gracias por tu tiempo.

    Saludos.

     

    • Editado WpfSoft martes, 30 de marzo de 2010 19:22
    martes, 30 de marzo de 2010 10:12
  • Hola WpfSoft.

    el punto 1 creo que es la explicacion, vamos con el siguiente.

    2.- para este ejemplo voy a usar un nuevo grid sin plantillas, de modo que el grid quedara de la siguiente forma:

            <DataGrid Height="251" HorizontalAlignment="Left"
                      Margin="12,12,0,0" x:Name="dataGrid1" VerticalAlignment="Top" Width="479" 
                      AlternatingRowBackground="LightSteelBlue" 
                      ItemsSource="{Binding}" SelectionUnit="FullRow" SelectionMode="Single" MouseLeftButtonUp="dataGrid1_MouseLeftButtonUp">
                
            </DataGrid>
    y en el evento MouseLeftButtonUp, se creara la fila nueva con los valores, y otra vacia

            private void dataGrid1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                if (dataGrid1.CurrentItem.GetType() == CollectionView.NewItemPlaceholder.GetType())
                {
                    // obtener la tabla con los datos enlazados al grid y crear una nueva fila
                    System.Data.DataRow row = ((System.Data.DataView)dataGrid1.ItemsSource).Table.NewRow();
                    row[1] = "nombre";
                    row[2] = "apellidos";
    
                    // agregar la fila a la tabla
                    ((System.Data.DataView)dataGrid1.ItemsSource).Table.Rows.Add(row);
                }
            }

    de este modo crearemos una fila nueva con datos(en mi caso nombre y apellidos ya que la columna 0 tiene un autoincremental).

     

    3.- Al realizar el paso anterior, la fila nueva se crea automaticamente

    4.- para realizar esto necesitas crearte el grid con plantillas de columna y personalizarlo, de la misma forma que he puesto en el 2 comentario, pero con una columna con el control que quieras.

    5.- para crear una fila se puede hacer con el codigo del punto 2

    6.- para esto puedes ampliar el evento anterior, algo como esto

            private void dataGrid1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                if (dataGrid1.CurrentItem.GetType() == CollectionView.NewItemPlaceholder.GetType())
                {
                    // obtener la tabla con los datos enlazados al grid y crear una nueva fila
                    System.Data.DataRow row = ((System.Data.DataView)dataGrid1.ItemsSource).Table.NewRow();
                    row[1] = "nombre";
                    row[2] = "apellidos";
    
                    // agregar la fila a la tabla
                    ((System.Data.DataView)dataGrid1.ItemsSource).Table.Rows.Add(row);
                }
                else
                {
                    System.Data.DataRow row = ((System.Data.DataRowView)dataGrid1.SelectedItem).Row;
                }
            }
    de forma que si la fila es nueva, la crea y si no, obtiene los datos en la variable row.

     

    Para el ultimo comentario lo tengo que mirar con algo de tiempo, ya que requiere interceptar el enlace a datos e ir creando las filas del grid dinamicamente, lo que hace que tengas que generar todas las filas del grid mediante programacion. Si lo necesitas, me lo comentas y le echo un vistazo.

     

    En cuanto a los bugs, es como la seguridad, no existe un sistema totalmente seguro, de la misma forma que no existe un software sin bugs, de echo mira los propios sistemas operativos sacan parches y actualizaciones para corregirlos.

    Pero en un principio, una version Release esta muy probada y si se añade algun pache se soluciona con la siguiente version.

    Por otro lado el componente datagrid forma parte de la toolkit WPF que es independiente de VS, de forma que te la puedes descargar en:

    http://wpf.codeplex.com/releases/view/40535

    donde tambien te puedes informar de los fallos, soluciones y mejoras.

    Ya me contaras como te va.


    Saludos
    David González
    martes, 30 de marzo de 2010 19:21
  • Hola David, muchas gracias como siempre, lo de crear los grid dinamicamente me interesa bastante, por supuesto cuando tu puedas, una cosa, los dos metodos que me has enviado no funcionan para recoger los datos en celleditendign?, esque los he implementado y no me funcionan, para mi es muy importante que normalmente se haga poco uso del raton al editar las filas, normalmente por rapidez, me gusta mas el teclado.

    Otra cosa David, existe un metodo para recoger los datos del row actualizados, a ver si me explico, con el codigo que te expongo a continuacion obtengo todos los datos del row pero no esta modificado el del textbox en cuestion, me devuelve los datos sin la modificacion realizada, a continuacion te expongo el codigo.

     

          private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                
                DataRowView drv = e.Row.Item as DataRowView;
                int idR = (int)drv.Row[0];
                string usuarioR = drv.Row[1].ToString();
                string passwordR = drv.Row[2].ToString();
                string nombreR = drv.Row[3].ToString();
                string apellidosR = drv.Row[4].ToString();
    
                MessageBox.Show("ID : " + idR.ToString() + " USUARIO : " 
    + usuarioR + " PASSWORD : " + passwordR + " NOMBRE : " + nombreR + " 
    APELLIDOS : " + apellidosR);
    
            }
    

     

    He implementado el codigo que me enviastes en otro post para recoger los datos del listview pero no me funcionan tampoco.

    Sabes si el datagrid del vs 2010 es el mismo que le del tools?, yo estoy utilizando el primero.

    Saludos y muchas gracias.

    martes, 30 de marzo de 2010 21:06
  • Hola WpfSoft.

    El Datagrid de la toolkit no es el mismo que el de VS2010, el VS2008 no tenia datagrid y habia que usar el de la toolkit, pero el VS2010 biene con un datagrid, si tienes instalada la toolkit puedes ver los 2. Para los ejemplos que te pongo yo hago uso del control de VS2010 ya que intento siempre no recurrir a librerias externas y he comprobado tambien que esta version es algo mas completa.

    a ver si tengo algo de tiempo y te miro la generacion dinamica de plantillas que es algo que quiero comprobar.


    Saludos
    David González
    jueves, 1 de abril de 2010 18:16
  • Hola WpfSoft.

    Para que te funcionasen los metodos y para obtener actualizados los elementos tienes que implementar la plantilla de edicion, en los ejemplos que has puesto solo tienes la plantilla normal (de lectura), se deben implementar las 2, algo como:

     

                    <DataGridTemplateColumn Header="nombre" Width="70">
                        <!-- plantilla para el modo lectura del grid -->
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate x:Name="prueba2">
                                <TextBlock Name="name" Text="{Binding Mode=TwoWay, Path=name}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                        <!-- plantilla para el modo edicion del grid -->
                        <DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate x:Name="prueba">
                                <TextBox Name="nameEdit" Text="{Binding Mode=TwoWay, Path=name}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellEditingTemplate>
                    </DataGridTemplateColumn>

     

    de esta forma, cuando el grid entre en modo edicion, mostrara el control de la plantilla de edicion.

    No obstante, como veo que estas poniendo TextBox, no hace falta que uses la plantilla de edicion ya que un textBox siempre se puede editar.

    en el otro post te he puesto una forma de implementar lo que buscas:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/b96ff232-48bf-42b9-a6df-dd94b79bdb37

     

    En cuanto a la creacion dinamica de controles, se puede realizar y basandonos en lo que ya tenemos de la siguiente forma:

    en lugar de implementar los TextBox en las plantillas, se inserta un contenedor para poder insertar dentro lo que se desee cuando se va cargando, por ejemplo algo como esto:

     

                    <DataGridTemplateColumn Header="nombre" Width="70">
                        <!-- plantilla para el modo edicion del grid -->
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Loaded="nameEdit_Loaded">
                                </StackPanel>
                            </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

     

    De esta forma tenemos un panel para insertar lo que deseemos, de modo que en el evento 'Loaded' podemos hacer algo como esto:

     

            private void nameEdit_Loaded(object sender, RoutedEventArgs e)
            {
                // obtener el panel de la plantilla
                StackPanel panel = (StackPanel)e.OriginalSource;
    
                // guardar referencia al panel correspondiente
                m_list.Add(panel);
    
                // en los impares se inserta un TextBox
                if (m_list.Count % 2 == 0)
                {
                    // crear el TextBox
                    TextBox text = new TextBox();
                    // crear el binding para el textbox
                    text.SetBinding(TextBox.TextProperty, "name");
                    text.KeyDown += new KeyEventHandler(pulsarTeclaEnter);
    
                    // añadir el control al contenedor de la plantilla
                    panel.Children.Add(text);
                }
                // en los pares se inserta un TextBlock
                else
                {
                    // crear el TextBox
                    TextBlock text = new TextBlock();
                    // crear el binding para el textbox
                    text.SetBinding(TextBlock.TextProperty, "surname");
    
                    // añadir el control al contenedor de la plantilla
                    panel.Children.Add(text);
                }
    
            }

     

    en este ejemplo inserto un TexBlock en las columnas impares y un TextBox en las pares (esto se debe hacer como se desee, tan solo es un ejemplo para ver como insertar un control en una celda concreta) de esta forma, cada celda puede tener un control diferente.

    Los contenedores se van almacenando en una lista generica de tipo 'FrameworkElement' como esta:

     

    private List<FrameworkElement> m_list = new List<FrameworkElement>();

     

    de forma que puedas acceder luego a los controles como se desee.

    En el TextBox he implementado el evento 'KeyDown' como en los otros ejemplos tuyos, de forma que se pueda implementar este evento para pasar el foco de uno a otro como en el link que he puesto antes.

    Si tienes alguna duda comentamelo.

     

    Saludos
    David González
    • Marcado como respuesta WpfSoft domingo, 4 de abril de 2010 9:30
    sábado, 3 de abril de 2010 22:29
  • Muchas gracias David por tus respuestas, voy a implementar tus ejemplos.
    domingo, 4 de abril de 2010 9:30
  • Hola amigos,

    Estaba buscando en la Web un problema que tengo y llegue a este forum. Les lanzo la pregunta a ver si me pueden ayudar. Estoy trabajando con el datagrid del toolkit en WPF. Puese ser que la pregunta les parezca trivial, si es asi mucho mejor. Como puedo saber si una celda del datagrid esta en modo de edicion, y en caso positivo actualizar su valor.

    Muchas gracias por adelantado.

    Carlos

     

    viernes, 16 de abril de 2010 20:08
  • Hola Carlos.

    ¿el evento CellEditEnding no te vale?, ocurre al terminar de editar una celda, de modo que puedes obtener la celda editada y actualizarla en la BBDD


    Saludos
    David González
    lunes, 19 de abril de 2010 7:07
  • Hola David,

      Muchas gracias por tu respuesta, pero tengo una gran duda y ojala me puedas ayudar, te explico. Tengo un datagrid y tres botones externos al datagrid que en el evnto click de cada uno de ellos obtengo la celda especifica del datagrid para editarla, con eso no hay problema ninguno. El problema es que tengo otros botones externos (simulando un keyboard numerico) y lo que quiero es que cuando el user haga click sobre alguno de estos botones ponga el valor del boton en la celda que esta en edicion. No se si me he explicado lo suficiente, pero no se de que manera saber si alguna celda esta en edicion y como asignarle el valor a la misma.

    Saludos

     

    Carlos Cabrera

     

    lunes, 19 de abril de 2010 13:52
  • Hola David,

      Muchas gracias por tu respuesta, pero tengo una gran duda y ojala me puedas ayudar, te explico. Tengo un datagrid y tres botones externos al datagrid que en el evnto click de cada uno de ellos obtengo la celda especifica del datagrid para editarla, con eso no hay problema ninguno. El problema es que tengo otros botones externos (simulando un keyboard numerico) y lo que quiero es que cuando el user haga click sobre alguno de estos botones ponga el valor del boton en la celda que esta en edicion. No se si me he explicado lo suficiente, pero no se de que manera saber si alguna celda esta en edicion y como asignarle el valor a la misma.

    Saludos

     

    Carlos Cabrera

     

    lunes, 19 de abril de 2010 13:52
  • Hola Carlos.

    Los 3 primeros botones no se que hacen en realidad, pero cuando tu pulsas un boton del teclado numerico, puedes acceder a la fila seleccionada y modificar el valor que quieras con algo como esto:

    System.Data.DataRow rowView = ((System.Data.DataRowView)dataGrid1.SelectedItem).Row; 

    Mediante esto obtienes una fila y puedes editar sus columnas como quieras.

     

     


    Saludos
    David González
    lunes, 19 de abril de 2010 16:05
  • hola david espero que te encuentres bien.

    estoy yo necesito algo un poco diferente, quiero colocar desde programa datos en una columna determinada del data grid. como lo podria hacer.

    de antemano muchas gracias,

    Lindbergh Zambrano

    martes, 18 de mayo de 2010 22:36
  • Hola Lindbergh.

    El dataGrid de wpf, realmente solo es una representacion visual de los datos y dado que la tecnologia WPF/silverlight hace uso del binding para establecer relaciones entre los datos, esto significa que no existe como en otras tecnologias una vista que es la que muestra el datagrid, si no que se muestra directamente los datos desde el enlace.

    Una vez dicho esto, si tu fuente de datos por ejemplo es un xml, el itemSource e items del datagrid seran esos mismos elementos, en caso de ser una vista, seran dataRowView (o algo similar).

    Por lo tanto para modificar una celda del DataGrid debes de modificar los item o itemSource y estos seran del tipo de objeto que hayas enlazado al grid.

    Si comentas cual es el objeto fuente de datos del grid, podria ser mas especifico, aunque el concepto es el que te he comentado.


    Saludos
    David González
    miércoles, 19 de mayo de 2010 10:15
  • hola david, lo que necesito es por decirte el valor de una variable pegarla en una celda especifica del datagrid.

    gracias amigo

    jueves, 20 de mayo de 2010 0:02
  • Hola Lindbergh.

    Supongo que la variable ademas la quieres guardar luego en el origen de datos ¿no?, si no no tiene mucho sentido.

    De ser asi, tienes que insertar la variable dependiendo de la fuente enlazada

    ¿como enlazas el datagrid, cual es su fuente de datos ItemSource?


    Saludos
    David González
    jueves, 20 de mayo de 2010 6:18
  • Hola David, tengo un problema, al recoger los datos de una fila en un datagrid, intento hacerlo así, tal y como encontré en este post.

     

    DataRowView drv = dataGrid1.CurrentCell.Item as
     DataRowView;
    if (drv!= null )
    {
    string cod = drv.Row[0].ToString();
    MessageBox.Show(cod);
    }

    Quiero desglosar la fila y recoger los datos, el messagebox lo uso para ver si saca el primer campo de la fila, la finalidad es que al editar la fila, recoja todos los datos y haga un update en la base de datos.

    El problema es que el datagrid.CurrentCell.Item tiene todos los datos de la fila seleccionada, pero drv es nula.

    ¿Me falta algún paso para rellenar drv?

    Gracias de antemano.

    jueves, 20 de mayo de 2010 7:54
  • Hola Donpituti.

    ¿como enlazas los datos?, el ejemplo es para un enlace de un dataview/datatable, si haces uso de otro origen de datos no es valida esa conversion, ya que el datagrid solo muestra los datos enlazados a el y no tiene ninguna copia  de los mismos.

    comprueba el tipo de objeto que es: dataGrid1.CurrentCell.Item

    a ver que tipo de objeto tiene.


    Saludos
    David González
    jueves, 20 de mayo de 2010 13:17
  • Hola otra vez David.

    Con un messageBox y getType me sale MS.Internal.NamedObject

    MessageBox.Show(dataGrid1.CurrentCell.Item.GetType().ToString());

     

    Estoy usando una consulta Linq para rellenar el datagrid.

     

    Gracias de nuevo.

     

     

    jueves, 20 de mayo de 2010 14:37
  • hola donpituti.

    El problema lo tienes ahi, si dices que obtienes una fuente de una consulta linq no vas a poder hacer un cast a un datarowView.

    Si puedes pon un punto de interrupcion, en lugar de un MessageBox y mira concretamente el tipo.

    En cualquier caso, ¿que objeto concreto pasas al ItemSource?


    Saludos
    David González
    jueves, 20 de mayo de 2010 16:13
  • Hola David.

    Te pongo el trozo de código donde hago la consulta Linq y relleno el datagrid:

     

    public DataClasses1DataContext dcdc;

    dcdc = new DataClasses1DataContext();

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var consulta = from vi in dcdc.Clientes
                               select vi;
        dataGrid1.ItemsSource = consulta;
    }

    Un saludo.
    jueves, 20 de mayo de 2010 17:25
  • Hola DonPituti.

    deberias de probar a hacer algun cast a un objeto que puedas manejar correctamente, prueba a utilizar el metodo extensor 'CopyToDataTable' de la variable consulta de modo que te realice el binding de un datatable que sabras usar correctamente.

    No obstante deberias de conocer el objeto consulta que tipo de objeto es y establecerlo en lugar de usar var, ya que luego pasan cosas de estas, el uso de var hace que muchas veces se desconozca el tipo de objeto con el que estas trabajando y siempre hay que saber los tipos con los que se trabaja.

    pon un punto de interrupcion en la asignacion del ItemSource y mira en la ventana de inspeccion el tipo de objeto que es para poder hacer un cast explicito.


    Saludos
    David González
    jueves, 20 de mayo de 2010 19:28
  • Hola David

    tengo una tabla de productos y una tabla de detalle de factura.

    en el datagrid tengo enlazado un DataTable de la tabla de detalle de factura

    datagrid.DataContext = dt_detalle.DefaulView;

    dentro de la tabla de detalle de la factura hay un campo de id_producto. El cual debo de usar para buscar el producto en la trabla de producto y traerme la descripcion y el precio del producto. y estos son los datos que quiero pegar en las celda de descripcion y de precio del datagrid.

    Otra pregusta, como hago para que cuando presiones Enter tenga el mismo efecto que tabulador en el datagrid.

    Amigo de antemano muchas gracias por tus comentarios.

    Saludo.

    martes, 25 de mayo de 2010 18:09
  • Hola Lindbergh.

     

    1.- En cuanto a lo de la tecla enter, en estos post que te dejo, tratamos el tema, echales un vistazo:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/448d45df-5609-48b4-ab19-815fd0f3a12f/

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/b96ff232-48bf-42b9-a6df-dd94b79bdb37

     

    2.- el tema de pegar contenido en las celdas, estas enlazando una vista de una tabla por lo que veo, de modo que la fila en la que quieres añadir contenido la puedes obtener de la siguiente forma:

     

    DataRowView drv = dataGrid1.CurrentCell.Item as DataRowView;

     

    y como tenermos la vista de la fila, podemos acceder desde ella a la tabla que la contiene, que en tu caso sera dt_detalle. Modificando un valor en dt_detalle, sera modificado en el grid, ya que el grid tan solo es una representacion visual de la tabla dt_detalle (en tu caso la vista usada por defecto que ha podido ser filtrada).

     


    Saludos
    David González
    jueves, 27 de mayo de 2010 13:46
  • Hola david, te entiendo todo muy bien y lo habia pensado de esa manera, pero cuando tu añades un nuevo registro desde el DataGrid en la tabla no se agrega hasta que no alla finalizado el proceso en el datagrid. si trato de modificar en este momenta la tabla me dice que el registro no existe.

     

    Saludos,

    Lindbergh Zambrano

    jueves, 27 de mayo de 2010 14:40
  • Hola Lindbergh.

    Vale, creo que ya se lo que quieres hacer. si lo que quieres es insertar una fila que aun no existe vas a tener que ser tu el que la cree en la tabla. El dataGrid tiene el metodo BeginEdit y EndEdit que te va a permitir editar el contenido del mismo, en algun post use esos metodos pero como hay tantos sobre el DataGrid, no lo encuentro, de modo que si quieres, puedes poner el codigo del datagrid xaml y partimos de ahi para intentar encontrar una solucion.


    Saludos
    David González
    jueves, 27 de mayo de 2010 15:52
  • ok david, pero ante te comento yp estoy usando VS2008 y vi que arriba comentabas que era preferible que trabajaran con VS2010.

    voy a instalar 2010 y te escribo.

    muchas gracias.

    jueves, 27 de mayo de 2010 16:22
  • hola david,

    Sabes que se me ocurrio que cuando precionara enter enviara un autamaticamente un un tabulador y hice esto:

    e.Handled =

     

    true;

     

     

    KeyEventArgs eInsertTab = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Tab);

    eInsertTab.RoutedEvent =

     

    UIElement.KeyDownEvent;

     

     

    InputManager.Current.ProcessInput(eInsertTab);

    y hace lo que yo quiero.

    amigo como hago para posicionarme en una celda en particular. por ejemplo quiero pasar el foco a la celda 2,1.

    saludo.

    martes, 1 de junio de 2010 14:20
  • Hola David,

     Como te habras dado cuenta soy bastante nuevo en WPF y no puedo aportar mucho, pero he hecho algunas cosas a partir de los buenos codigos que hay en Codeproject. Pero vamos al asunto, pues tengo un problema que no he podido resolver y necesito si es posible tu ayuda.

      Resulta que tengo un datagrid con un datatemplate que me define RowDetailsTemplate. Dentro del Rowdetails tengo definido un combobox, y no he podido encontrar la manera de poder referenciar el combobox en el code-behind. El intelligen-sense de VS no lo reconoce porque esta dentro de la plantilla del datagrid. he tratado con la funcion Findname del datagrid pero siempre me retorna un null. Como puedo referenciar en codigo un control en una plantilla del datagrid?

     

    De antemano muchas gracias

     

    Carlos Cabrera
     
    martes, 22 de junio de 2010 14:04
  • Hola carlos.

    Las plantillas en wpf/silverlight solo son eso, plantillas y no se pueden referenciar ya que solo son controles de lectura que se utilizan para crear los diferentes items, basicamente hay que hacerse la idea de que una plantilla es como una clase (no es del todo cierto pero si lo es el modo de comportamiento), no se puede obtener una referencia a una clase, ya que las clases son abstracciones o definiciones de objetos, solo se pueden referenciar los objetos que son la instancia de una clase concreta.

    Pues las plantillas hay que tratarlas de la misma forma, se puede acceder a la plantilla, pero para acceder al objeto creado por esa plantilla es otra cosa.

    Existen varios metodos comentados en el foro, pero te voy a comentar el mas sencillo a ver si te sirve.

    cuando creas la plantilla (supongo que en codigo xaml) en el objeto que quieras referenciar (en tu caso el combobox) le puedes meter el evento 'Loaded' de modo que en el codigo puedes implementar el evento para obtener la referencia al objeto y guardarlo en una variable miembro, de esta forma puedes acceder al objeto desde el codigo cuando quieras.

    un ejemplo esta en este mismo post (realiza una busqueda por 'Loaded' y te saldran los sitios donde se explica.

    Ya me contaras como te ha ido.


    Saludos
    David González
    jueves, 24 de junio de 2010 9:24
  • hola, como puedo agregar una fila a un datagrid que contiene 3 columnas?:( helppppppppp
    miércoles, 27 de octubre de 2010 15:47
  • ¡Hola!

    Por qué no te creas una pregunta en vez de preguntar en una pregunta ya cerrada. Tendrá más impacto.

     

    Saludos,

     

    P.D.: De todas formas creo que Yeray ya respondió a esta cuestión a Spandau en el foro

    miércoles, 27 de octubre de 2010 16:04
  • ya la abri:( desde hace dias pero nadie:( me ayuda:( y bueno volvere abrir otra haber si tengo suerte y mm voy a buscar a yeray gracias:)
    miércoles, 27 de octubre de 2010 17:07
  • Pero es que vamos a ver.... Que clase de programador o tonto (que da mejor con la definicion) pone todoo el puto código? Saber depurar y buscar los fallos es el gran arte de programación.... tienes que buscar el fallo de tu programa, parandolo en ciertos puntos donde crees que está el error... es un abuso pedir a la gente que lea tal tocho de texto y hacerles peder el tiempo.

    Un ejemplo

    int x = 2;

    float y = 1.5;

    x = y;

    donde está el fallo? pues que son incompatibles los tipos :S

    jueves, 8 de marzo de 2012 13:40
  • Hola DientesDeCheto

    Aquí estamos para ayudar a las demás personas... nosotros "donamos" parte de nuestro tiempo... si a esta pregunta se le dio respuesta fue porque varios de los colaboradores de este foro leyeron todo ese código para ayudar a un colega. Pero si a usted no le gusta y/o le intimida leer tanto código, cordialmente le invito a que no de respuestas tan molestas y que pueden herir susceptibilidades. 

    Un saludo


    Antonio Lobo
    Para el correcto funcionamiento, y que otros usuarios se puedan beneficiar de la solucion de esta pregunta por favor marca las respuestas que te hayan ayudado como "Respuesta".
    Si la respuesta te ha sido util Votala.
    Mi blog

    jueves, 8 de marzo de 2012 14:22
  • Hola david buen dia espero te encuentres por aqui

    tengo una pregunta para este codigo

    dataGridNosDeParte.ItemsSource = Lista;
    MessageBox.Show(Lista[0].Alias);
    Lista[0].Alias = "Rodolfo";

    el valor Rodolfo si se almacena en la lista pero no se actualiza en el DataGrid WPF

    podras ayudarme?   gracias!

    martes, 27 de diciembre de 2016 15:56