none
Como recoger Datos enviados desde un Listview ? RRS feed

  • Pregunta

  • Hola amigos, esta es mi pregunta sobre WPF , yo tengo un listview en el cual hay un datatemplate, el listview lo relleno con datos sacados de la DDBB, hasta aqui sin problemas, se muestran todos los datos en el listview, estos son 4 textbox y un boton, la idea era que al modificar cualquier valor del textbox al pulsar en el boton se editara o si fuese posible al salir con mouseleave se editara solo, pero me encuentro con un grave problema,  no me aparecen las instancias de los textbox, me he dado cuenta que al estar dentro de un datatemplate no me aparecen y entonces no se como recoger los datos, el boton si lo puedo recoger con commandparameter pero eso no me vale ya que solo obtengo la id, os pongo el codigo del xaml.

    <Window x:Class="app1.vistaListadoUsuarios"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="vistaListadoUsuarios" Height="436.25" Width="811.25">
            <Grid x:Name="Grid1">
            <StackPanel Orientation="Horizontal" Margin="5">
                <StackPanel Width="40" Background="DarkBlue" Height="20" HorizontalAlignment="Left" Margin="7.5,4,0,0" VerticalAlignment="Top">
                    <TextBlock FontSize="12" Height="20" Width="40" Foreground="White" TextAlignment="Center">ID</TextBlock>
                </StackPanel>
                <StackPanel Width="90" Background="DarkBlue" Height="20" HorizontalAlignment="Left" Margin="0,4,0,0" VerticalAlignment="Top">
                    <TextBlock FontSize="12" Height="20" Width="90" Foreground="White" TextAlignment="Center">USUARIO</TextBlock>
                </StackPanel>
                <StackPanel Width="90" Background="DarkBlue" Height="20" HorizontalAlignment="Left" Margin="0,4,0,0" VerticalAlignment="Top">
                    <TextBlock FontSize="12" Height="20" Width="90" Foreground="White" TextAlignment="Center">PASSWORD</TextBlock>
                </StackPanel>
                <StackPanel Width="90" Background="DarkBlue" Height="20" HorizontalAlignment="Left" Margin="0,4,0,0" VerticalAlignment="Top">
                    <TextBlock FontSize="12" Height="20" Width="90" Foreground="White" TextAlignment="Center">NOMBRE</TextBlock>
                </StackPanel>
                <StackPanel Width="90" Background="DarkBlue" Height="20" HorizontalAlignment="Left" Margin="0,4,0,0" VerticalAlignment="Top">
                    <TextBlock FontSize="12" Height="20" Width="90" Foreground="White" TextAlignment="Center">APELLIDOS</TextBlock>
                </StackPanel>
         </StackPanel>
        <ListView Margin="12,28,186.25,40" Name="ListadoUsuarios"  ItemsSource="{Binding Path=Table}" Background="Lavender" MouseDoubleClick="ListadoUsuarios_MouseDoubleClick" >
                <ListView.ItemTemplate>
                  <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="5">
                            <StackPanel Margin="2" Width="20">
                               <TextBox Name="idListadoVista" FontWeight="Bold" FontSize="12" Text="{Binding Path=id}"/>
                            </StackPanel>
                            <StackPanel Margin="2" Width="100">
                                <TextBox Name="usuarioListadoVista" FontWeight="Bold" FontSize="12" Text="{Binding Path=usuario}"/>
                            </StackPanel>
                            <StackPanel Margin="2" Width="100">
                                <TextBox Name="passwordListadoVista" FontWeight="Bold" FontSize="12" Text="{Binding Path=password}"/>
                            </StackPanel>
                            <StackPanel Margin="2" Width="100">
                                <TextBox Name="nombreListadoVista" FontWeight="Bold" FontSize="12" Text="{Binding Path=nombre}"/>
                            </StackPanel>
                            <StackPanel Margin="2" Width="100">
                                <TextBox Name="apellidosListadoVista" FontWeight="Bold" FontSize="12" Text="{Binding Path=apellidos}"/>
                            </StackPanel>
                            <StackPanel>
                                <Button Name="Editar" Width="50" Click="actualizarUsuario" CommandParameter="{Binding Path=id}">Editar</Button>
                            </StackPanel>
                            <StackPanel>
                                <Button Name="Borrar" Width="50" Click="borrarUsuario" CommandParameter="{Binding Path=id}">Borrar</Button>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    </Window>
    Y este es el codigo de ejemplo para coger el valor del boton Editar que lo recogo sin problemas, para mi lo mas importante es saber como recogo los demas datos de la fila seleccionada, o sea el usuario, password, nombre y apellidos.

    codigo para recoger el valor del boton Editar.

    private void actualizarUsuario(object sender, RoutedEventArgs e)
            {
               
                Button boton = new Button();
                boton = (Button)sender;
                string valor = boton.CommandParameter.ToString();
                
                MessageBox.Show(valor);
                     
            }
    Muchas gracias por la molestia y vuestro tiempo.

    martes, 2 de marzo de 2010 21:31

Respuestas

  • Hola de nuevo WpfSoft.

    debido al doble click que comentas, se tiene que crear otro mecanismo diferente al que te propuse la primera vez, en realidad es casi igual pero en lugar de tratar los controles, se trataran directamente los datos y de paso es un buen ejemplo para que se vea el funcionamiento de los evento enrutados.

    Basandonos en tu primer codigo, deberas de poner los siguientes eventos en el ListView:

    <ListView Margin="12,28,110.5,29" Name="ListadoUsuarios"  Background="Lavender" LostFocus="StackPanel_LostFocus" MouseDoubleClick="ListadoUsuarios_MouseDoubleClick">  

    Los eventos de los botones, los dejaremos como te comente en el post anterior.

    Ahora en el codigo c#, se definen los eventos de la siguiente forma (esto es un ejemplo y se puede optimizar para obtener los datos y no tener que repetir el mismo codigo, pero lo dejo al gusto)

    /// <summary>
    /// Evento para los botones de las filas del ListView
    /// </summary>
    /// <param name="sender">objeto remitente</param>
    /// <param name="e">Argumentos del evento</param>
    private void btn_click(object sender, RoutedEventArgs e)
    {
        // obtener el panel principal de la lista para el elemento UI que ha generado el evento        
        System.Data.DataRowView data = getListItem((FrameworkElement)e.OriginalSource);
    
        if (data != null)
        {
            // obtener las columnas deseadas
            string id = data.Row["id"].ToString();
            string usuario = data.Row["usuario"].ToString();
    
            // ... Mas columnas
    
            // evaluar el boton pulsado y actuar en consecuencia
            switch (((FrameworkElement)e.Source).Name)
            {
                // Boton Editar pulsado
                case "Editar":
    
                    // mostrar mensaje
                    MessageBox.Show("Editada fila con id: " + id + " y usuario: " + usuario);
    
                    break;
    
                // Boton Borrar pulsado
                case "Borrar":
    
                    // mostrar mensaje
                    MessageBox.Show("Borrar fila con id: " + id + " y usuario: " + usuario);
    
                    break;
            }
        }
    }
    
    /// <summary>
    /// Evento para la perdida del foco en cualquier control dentro del listView
    /// </summary>
    /// <param name="sender">Objeto remitente</param>
    /// <param name="e">argumentos del evento</param>
    private void StackPanel_LostFocus(object sender, RoutedEventArgs e)
    {
        // evaluar el control fuente que ha perdido el foco
        switch (e.OriginalSource.GetType().Name)
        {
            case "TextBox":
    
                // obtener el textBox que ha perdido el foco
                TextBox text = (TextBox)e.OriginalSource;
    
                // TODO: si se quiere se puede obtener el panel con las columnas
                // obtener el panel principal de la lista para el elemento UI que ha generado el evento        
                //System.Data.DataRowView data = getListItem((FrameworkElement)e.OriginalSource);
    
                //if (data != null)
                //{
                //    // obtener las columnas deseadas
                //    string id = data.Row["id"].ToString();
                //    string usuario = data.Row["usuario"].ToString();
    
                //    // ... Mas columnas
                //}
    
                // mostrar mensaje
                MessageBox.Show("Perdido el foco en el TextBox: " + text.Text);
    
                break;
    
            default:
                break;
        }            
    }
    
    /// <summary>
    /// Evento para el doble click en cualquier punto dentro del listView
    /// </summary>
    /// <param name="sender">Objeto remitente</param>
    /// <param name="e">argumentos del evento</param>
    private void ListadoUsuarios_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        // obtener el panel principal de la lista para el elemento UI que ha generado el evento        
        System.Data.DataRowView data = getListItem((FrameworkElement)e.OriginalSource);
    
        if (data != null)
        {
            // obtener las columnas deseadas
            string id = data.Row["id"].ToString();
            string usuario = data.Row["usuario"].ToString();
    
            // ... Mas columnas
    
            // mostrar mensaje
            MessageBox.Show("doble click en la fila con id: " + id + " y usuario: " + usuario);
        }
    }    
    
    
    /// <summary>
    /// Funcion para obtener los datos de un item de la lista mediante
    /// cualquier elemento UI interno
    /// </summary>
    /// <param name="_element">elemento UI interno de un ListViewItem</param>
    /// <returns>DataRowView con los datos de la fila</returns>
    private System.Data.DataRowView getListItem(FrameworkElement _element)
    {
        if (_element != null)
        {
            // obtener el item de la lista
            ListViewItem item = (ListViewItem)ListadoUsuarios.ContainerFromElement(_element);
            if (item != null)
            {
                // obtener el indice del item de la lista
                int index = ListadoUsuarios.ItemContainerGenerator.IndexFromContainer(item);
                // retornar la vista de la fila con los datos
                return (System.Data.DataRowView)ListadoUsuarios.Items[index];
            }
        }
    
        // si no se encuentra se retorna null
        return null;
    }

    Como se puede observar el corazon de todo esto es la funcion "getListItem" que obtiene la vista de la fila con los datos, de modo que no hace falta trastear con los controles y saber la herencia del arbol WPF como te puse en el ejemplo anterior.

    Se puede decir que esta es una forma mucho mas abstracta para casi todo tipo de casos.

    Si no entiendes algo comentalo.







    Saludos
    David González
    jueves, 4 de marzo de 2010 8:23

Todas las respuestas

  • Hola WpfSoft.

    De la forma que lo tienes montado posiblemente la mejor forma de obtener los datos es de la siguiente forma:

    1.- en los eventos Click de los button, no hace falta crear eventos separados, asi que yo les añado el mismo evento de esta forma:

    <StackPanel>
        <Button Name="Editar" Width="50" Click="btn_click" CommandParameter="{Binding Path=id}">Editar</Button>
    </StackPanel>
    <StackPanel>
        <Button Name="Borrar" Width="50" Click="btn_click" CommandParameter="{Binding Path=id}">Borrar</Button>
    </StackPanel>

    2.- con lo anterior podemos definir un evento unico para ambos botones y obtener el boton correspondiente ademas de obtener los datos
     de la siguiente forma:

            /// <summary>
            /// Evento para los botones de las filas del ListView
            /// </summary>
            /// <param name="sender">objeto remitente</param>
            /// <param name="e">Argumentos del evento</param>
            private void btn_click(object sender, RoutedEventArgs e)
            {
                // NOTA: esto no es necesario (no hay que crear un boton)
                //Button boton = new Button();
                
                // NOTA: en WPF existe otra opcion para eventos enrutados 
                // se puede hacer asi, pero la de abajo da mas juego
                //boton = (Button)sender;
                // Mediante esto se puede obtener la fuente del evento
                Button boton = (Button)e.Source;
    
                // obtener el contenedor del boton
                StackPanel panel = (StackPanel)boton.Parent;
                // obtener el contenedor principal del item
                StackPanel mainPanel = (StackPanel)panel.Parent;
    
                // obtener las columnas deseadas
                panel = (StackPanel)mainPanel.Children[0];
                string id = ((TextBox)panel.Children[0]).Text;
    
                panel = (StackPanel)mainPanel.Children[1];
                string usuario = ((TextBox)panel.Children[0]).Text;
    
                // ... Mas columnas
    
                // evaluar el boton pulsado y actuar en consecuencia
                switch (boton.Name)
                {
                    // Boton Editar pulsado
                    case "Editar":
    
                        // mostrar mensaje
                        MessageBox.Show("Editada fila con id: " + id + " y usuario: " + usuario);
    
                        break;
    
                    // Boton Borrar pulsado
                    case "Borrar":
    
                        // mostrar mensaje
                        MessageBox.Show("Borrar fila con id: " + id + " y usuario: " + usuario);
    
                        break;
                }
            }

    Esta posiblemente sea la mejor forma para el codigo que tienes escrito.

    Si tienes alguna duda comentalo.





    Saludos
    David González
    miércoles, 3 de marzo de 2010 9:18
  • Muchas gracias David, me ha funcionado correctamente, mi duda era como recoger las variables y me lo has resuelto, si no te importa te comento otra duda, te comento, basandonos en el codigo anterior mi idea es actualizar los registros cuando se salga de un textbox, en wpf es posible asignar a los textbox funciones del tipo mouse?, me explico, por ejemplo al salir de el con el raton, es para poder actualizar los registros sin tener que pulsar el boton editar, otra cosa David, como puedo recoger con la funcion mousedoubleclick los datos del registro en el cual he pulsado dos veces.

    Muchas gracias por tus respuestas.


    miércoles, 3 de marzo de 2010 9:51
  • Hola de nuevo WpfSoft.

    debido al doble click que comentas, se tiene que crear otro mecanismo diferente al que te propuse la primera vez, en realidad es casi igual pero en lugar de tratar los controles, se trataran directamente los datos y de paso es un buen ejemplo para que se vea el funcionamiento de los evento enrutados.

    Basandonos en tu primer codigo, deberas de poner los siguientes eventos en el ListView:

    <ListView Margin="12,28,110.5,29" Name="ListadoUsuarios"  Background="Lavender" LostFocus="StackPanel_LostFocus" MouseDoubleClick="ListadoUsuarios_MouseDoubleClick">  

    Los eventos de los botones, los dejaremos como te comente en el post anterior.

    Ahora en el codigo c#, se definen los eventos de la siguiente forma (esto es un ejemplo y se puede optimizar para obtener los datos y no tener que repetir el mismo codigo, pero lo dejo al gusto)

    /// <summary>
    /// Evento para los botones de las filas del ListView
    /// </summary>
    /// <param name="sender">objeto remitente</param>
    /// <param name="e">Argumentos del evento</param>
    private void btn_click(object sender, RoutedEventArgs e)
    {
        // obtener el panel principal de la lista para el elemento UI que ha generado el evento        
        System.Data.DataRowView data = getListItem((FrameworkElement)e.OriginalSource);
    
        if (data != null)
        {
            // obtener las columnas deseadas
            string id = data.Row["id"].ToString();
            string usuario = data.Row["usuario"].ToString();
    
            // ... Mas columnas
    
            // evaluar el boton pulsado y actuar en consecuencia
            switch (((FrameworkElement)e.Source).Name)
            {
                // Boton Editar pulsado
                case "Editar":
    
                    // mostrar mensaje
                    MessageBox.Show("Editada fila con id: " + id + " y usuario: " + usuario);
    
                    break;
    
                // Boton Borrar pulsado
                case "Borrar":
    
                    // mostrar mensaje
                    MessageBox.Show("Borrar fila con id: " + id + " y usuario: " + usuario);
    
                    break;
            }
        }
    }
    
    /// <summary>
    /// Evento para la perdida del foco en cualquier control dentro del listView
    /// </summary>
    /// <param name="sender">Objeto remitente</param>
    /// <param name="e">argumentos del evento</param>
    private void StackPanel_LostFocus(object sender, RoutedEventArgs e)
    {
        // evaluar el control fuente que ha perdido el foco
        switch (e.OriginalSource.GetType().Name)
        {
            case "TextBox":
    
                // obtener el textBox que ha perdido el foco
                TextBox text = (TextBox)e.OriginalSource;
    
                // TODO: si se quiere se puede obtener el panel con las columnas
                // obtener el panel principal de la lista para el elemento UI que ha generado el evento        
                //System.Data.DataRowView data = getListItem((FrameworkElement)e.OriginalSource);
    
                //if (data != null)
                //{
                //    // obtener las columnas deseadas
                //    string id = data.Row["id"].ToString();
                //    string usuario = data.Row["usuario"].ToString();
    
                //    // ... Mas columnas
                //}
    
                // mostrar mensaje
                MessageBox.Show("Perdido el foco en el TextBox: " + text.Text);
    
                break;
    
            default:
                break;
        }            
    }
    
    /// <summary>
    /// Evento para el doble click en cualquier punto dentro del listView
    /// </summary>
    /// <param name="sender">Objeto remitente</param>
    /// <param name="e">argumentos del evento</param>
    private void ListadoUsuarios_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        // obtener el panel principal de la lista para el elemento UI que ha generado el evento        
        System.Data.DataRowView data = getListItem((FrameworkElement)e.OriginalSource);
    
        if (data != null)
        {
            // obtener las columnas deseadas
            string id = data.Row["id"].ToString();
            string usuario = data.Row["usuario"].ToString();
    
            // ... Mas columnas
    
            // mostrar mensaje
            MessageBox.Show("doble click en la fila con id: " + id + " y usuario: " + usuario);
        }
    }    
    
    
    /// <summary>
    /// Funcion para obtener los datos de un item de la lista mediante
    /// cualquier elemento UI interno
    /// </summary>
    /// <param name="_element">elemento UI interno de un ListViewItem</param>
    /// <returns>DataRowView con los datos de la fila</returns>
    private System.Data.DataRowView getListItem(FrameworkElement _element)
    {
        if (_element != null)
        {
            // obtener el item de la lista
            ListViewItem item = (ListViewItem)ListadoUsuarios.ContainerFromElement(_element);
            if (item != null)
            {
                // obtener el indice del item de la lista
                int index = ListadoUsuarios.ItemContainerGenerator.IndexFromContainer(item);
                // retornar la vista de la fila con los datos
                return (System.Data.DataRowView)ListadoUsuarios.Items[index];
            }
        }
    
        // si no se encuentra se retorna null
        return null;
    }

    Como se puede observar el corazon de todo esto es la funcion "getListItem" que obtiene la vista de la fila con los datos, de modo que no hace falta trastear con los controles y saber la herencia del arbol WPF como te puse en el ejemplo anterior.

    Se puede decir que esta es una forma mucho mas abstracta para casi todo tipo de casos.

    Si no entiendes algo comentalo.







    Saludos
    David González
    jueves, 4 de marzo de 2010 8:23
  • Muchas gracias David González.
    Saludos
    viernes, 5 de marzo de 2010 14:32