none
Guardar valores en ListView columnas especificas RRS feed

  • Pregunta

  • Que tal a todos,

    Estoy llenando un ListView desde una base de datos SqlServer y estoy agregando cuatro columnas vacías para agregarles un valor al mismo ListView con eventos del Teclado o Mouse.

    Tengo este código lo que hace es llenar un ListView vacio desde el SubItem 0.

    Para no tener dos ListView quisiera poder indicarle al método que me agregue los valores al listview que lleno con los datos de la base de datos (las columnas vacias, 7,8,9 y 10)

    Este es el metodo con el que lleno el ListView vacío:

    private void LogWrite(string txt)
            {
                string[] lineItems = txt.Split('-');//Separas la cadena por el carácter '-'
                listCapture.CheckBoxes = true;
                lv = new ListViewItem(txt);  //en un array y obtienes la posición 0
                lv.Text = lineItems[0]; // en un array y obtienes la posición 1
                lv.SubItems.Add(lineItems[1]);
                lv.SubItems.Add(lbl_x.Text.ToString());
                lv.SubItems.Add(lbl_y.Text.ToString());
                listCapture.Items.Add(lv);
                count = count + 1;
                lblItems.Text = "Total events: " + count.ToString();
            }

    Y este el metodo para llenar el listView con los datos del Sql y las columnas vacias:

    private void loadListView()
            {
                try
                {
                    SqlCommand cmd = new SqlCommand("NewLearning", cnx);
                    cmd.CommandType = CommandType.StoredProcedure;
                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    /*da.Fill(dt);
                    cmbSelectApp.ValueMember = "idApplication";
                    cmbSelectApp.DisplayMember = "nameApplication";
                    cmbSelectApp.DataSource = dt;*/
                    da.SelectCommand.CommandType = CommandType.StoredProcedure;
                    da.SelectCommand.Parameters.AddWithValue("@IdApplication", cmbSelectApp.SelectedValue);
                    da.Fill(dt);
                    listData.Clear();
                    listData.CheckBoxes = true;
                    listData.Columns.Add(dt.Columns[0].ToString(), 60);
                    listData.Columns.Add(dt.Columns[1].ToString(), 60);
                    listData.Columns.Add(dt.Columns[2].ToString(), 60);
                    listData.Columns.Add(dt.Columns[3].ToString(), 60);
                    listData.Columns.Add(dt.Columns[4].ToString(), 60);
                    listData.Columns.Add(dt.Columns[5].ToString(), 60);
                    listData.Columns.Add(dt.Columns[6].ToString(), 60);
                    listData.Columns.Add("Mouse or Key", 60);
                    listData.Columns.Add("Action", 60);
                    listData.Columns.Add("X", 60);
                    listData.Columns.Add("Y", 60);
    
    
    
                    foreach (DataRow row in dt.Rows)
                    {
                        string[] arr = new string[7];
                        ListViewItem itm = new ListViewItem();
    
                        for(int ncol = 0; ncol < 7; ncol++)
                        {
                            arr[ncol] = row[ncol].ToString();
                            itm = new ListViewItem(arr);
                        }
                        listData.Items.Add(itm);
                    }
                    cnx.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error try load to select Applications: " + ex.Message);
                }
            }

    Espero me puedan ayudar.

    Saludos

    DS


    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.

    jueves, 24 de septiembre de 2020 22:44

Respuestas

  • Hola Dany

    Busqué un poco más, y luego de entender como es la lógica y de un ratito de pruebas, te presento aquí el método SetToColAndRow(). Recibe el índice de la fila en la cual vas a poner el item, el índice de la columna, y el string del item. Lo que hace es, 1° verificar que la fila y la columna existan, caso contrario devuelve false y no hace nada; 2°, si existen la fila y la columna, recolecta todos los items de la fila en un array de string[] y le pone en la columna el valor de item, en las columnas que no hay nada pone un "" (string vacío), luego elimina la fila e inserta en el mismo lugar la misma fila con el nuevo item.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsAppListViewColumns
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                listView1.View = View.Details;
                listView1.FullRowSelect = true;
    
                listView1.Columns.Add("Column 1");
                listView1.Columns.Add("Column 2");
                listView1.Columns.Add("Column 3");
                listView1.Columns.Add("Column 4");
                listView1.Columns.Add("Column 5");
    
                ListViewItem items = new ListViewItem(new string[] { "item 1", "item 2", "item 3" });
                listView1.Items.Add(items);
    
                ListViewItem items2 = new ListViewItem(new string[] { "item 4", "item 5", "item 6" });
                listView1.Items.Add(items2);
    
                ListViewItem items3 = new ListViewItem(new string[] { "item 7", "item 8", "item 9" });
                listView1.Items.Add(items3);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                bool v = SetToColAndRow(4, 1, "item 15");
            }
    
            private bool SetToColAndRow(int colIndex, int rowIndex, string item) 
            {
                int a;
                string[] items;
                
                items = new string[listView1.Columns.Count];
                for (a = 0; a < listView1.Columns.Count; a++) 
                    items[a] = "";
    
                if (listView1.Items.Count <= rowIndex || colIndex >= listView1.Columns.Count)
                    return false;
    
                for (a = 0; a < listView1.Columns.Count; a++) 
                {
                    if (a == colIndex)
                        items[a] = item;
                    else
                    {
                        if (a < listView1.Items[rowIndex].SubItems.Count)
                            items[a] = listView1.Items[rowIndex].SubItems[a].Text;
                        else
                            items[a] = "";
                    }
                }
                listView1.Items.RemoveAt(rowIndex);
                listView1.Items.Insert(rowIndex, new ListViewItem(items));
                return true;
            }
        }
    }
    

    Espero te sea útil.

    Saludos

    Pablo

    domingo, 27 de septiembre de 2020 15:24

Todas las respuestas

  • Hola Dany Solis,

    No estoy seguro si entendí bien tu pregunta, pero me parece que en esta guía esta lo que ocupas. Espero que te sea de ayuda. Por favor no olvides marcar una respuesta si resolviste tu consulta (debajo de cada post hay una opción que dice “Marcar como Respuesta”). Quedo pendiente de cualquier actualización. Gracias por levantar tu consulta en los foros de msdn.

     

    Saludos cordiales

    Gabriel Castro

     ____________________________ 

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde. 

    viernes, 25 de septiembre de 2020 0:25
    Moderador
  • Hola Dany

    Googleé, porque yo tampoco sabía como asignar elementos de un ListView a sus diferentes columnas.

    https://stackoverflow.com/questions/473148/c-sharp-listview-how-do-i-add-items-to-columns-2-3-and-4-etc

    Yo te recomendaría que elimines los 2 bloques de código que pegaste, y que empieces de nuevo, tienen bastantes errores e inconsistencias.

    Por lo que leí en el link que pegué aquí, me parece que lo que tendrías que hacer es, 1° crear las 10 columnas del ListView, y luego iterar por todas las "filas", para esto tendrías que juntar lo que obtenes de la base de datos y luego lo otro, y cuando tenes los 10 elementos, digamos, de item1 a item10, lo que sería la fila cuyos items van a ir cada uno a su correspondiente columna, escribis:

    listData.Items.AddRange(new ListViewItem[] { item1, item2, item3, item4, item5, item6, item7, item8, item9, item10 });

    Esto, dentro del for, donde 1° "juntas" los 7 campos que provienen del DataTable y luego los otros 3 que no entendí bien que son ni de donde surgen porque el código no está muy bien. Así, vas llenando fila por fila el ListView, esto es, todas las columnas una celda cada vez.

    También, por lo que leí, hay otra forma de llenar el ListView, que es llenar las columnas completas de un saque una por una, pero me parece que en tu caso, por la forma en que vas obteniendo los datos (fila por fila), no da para usar ese método.

    Espero te sea útil.

    Saludos

    Pablo


    viernes, 25 de septiembre de 2020 0:35
  • Gracias por contestar, dejame extender un poco mas la pregunta.

    En el listview de la columna 0 a la 6 muestro los datos de una tabla sql y agrego cuatro columnas igual por código en la carga de estos datos pero estas columnas estan vacias ya que mediante eventos del boton o teclado ire guardando los eventos que realice el usuario ahora mostrare un ejemplo.

    Este codigo es el metodo de carga del listview con datos de la tabla Sql y las columnas vacias:

    private void FormMachineLearning_Load(object sender, EventArgs e)
            {
                loadData();
                loadListView();
            }
    
    //Con esta clase detecto los eventos del Mouse o Teclado
            private void loadData()
            {
                            actHook = new UserActivityHook(); // crate an instance with global hooks
                                                  // hang on events
                actHook.OnMouseActivity += new MouseEventHandler(MouseMoved);
                actHook.KeyDown += new KeyEventHandler(MyKeyDown);
                actHook.KeyPress += new KeyPressEventHandler(MyKeyPress);
                actHook.KeyUp += new KeyEventHandler(MyKeyUp);
    
                actHook.Stop();
                try
                {
                    //SqlCommand cmd = new SqlCommand("ShowNewApplications", cnx);
                    SqlCommand cmd = new SqlCommand("ListNewApplications", cnx);
                    cmd.CommandType = CommandType.StoredProcedure;
                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    da.Fill(dt);
                    cmbSelectApp.ValueMember = "idApplication";
                    cmbSelectApp.DisplayMember = "nameApplication";
                    cmbSelectApp.DataSource = dt;
                    cnx.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error try load to select Applications: " + ex.Message);
                }
                statusLst();
    
            }
    
            private void loadListView()
            {
                try
                {
                    SqlCommand cmd = new SqlCommand("NewLearning", cnx);
                    cmd.CommandType = CommandType.StoredProcedure;
                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    da.SelectCommand.CommandType = CommandType.StoredProcedure;
                    da.SelectCommand.Parameters.AddWithValue("@IdApplication", cmbSelectApp.SelectedValue);
                    da.Fill(dt);
                    listData.Clear();
                    listData.CheckBoxes = true;
    listData.Columns.Add(dt.Columns[0].ToString(), 60);
    listData.Columns.Add(dt.Columns[1].ToString(), 60);
    listData.Columns.Add(dt.Columns[2].ToString(), 60);
    listData.Columns.Add(dt.Columns[3].ToString(), 60);
    listData.Columns.Add(dt.Columns[4].ToString(), 60);
    listData.Columns.Add(dt.Columns[5].ToString(), 60);
    listData.Columns.Add(dt.Columns[6].ToString(), 60);
    listData.Columns.Add("Mouse or Key", 60);//aquí comienzan las columnas vacias
    listData.Columns.Add("Action", 60);
    listData.Columns.Add("X", 60);
    listData.Columns.Add("Y", 60);
    
    
    
                    foreach (DataRow row in dt.Rows)
                    {
                        string[] arr = new string[7];
                        ListViewItem itm = new ListViewItem();
    
                        for(int ncol = 0; ncol < 7; ncol++)
                        {
                            arr[ncol] = row[ncol].ToString();
                            itm = new ListViewItem(arr);
                        }
                        listData.Items.Add(itm);
                    }
                    cnx.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error try load to select Applications: " + ex.Message);
                }
            }

    Ahora lo que tengo para llenar un listView vacio y funcional es esto, detectando las acciones del Mouse o Teclado:

    private void LogWrite(string txt)
            {
                string[] lineItems = txt.Split('-');//Separas la cadena por el carácter '-'
                listCapture.CheckBoxes = true;
                lv = new ListViewItem(txt);  //en un array y obtienes la posición 0
                lv.Text = lineItems[0]; // en un array y obtienes la posición 1
                lv.SubItems.Add(lineItems[1]);
                lv.SubItems.Add(lbl_x.Text.ToString());
                lv.SubItems.Add(lbl_y.Text.ToString());
                listCapture.Items.Add(lv);
                count = count + 1;
                lblItems.Text = "Total events: " + count.ToString();
            }
            public void MouseMoved(object sender, MouseEventArgs e)
            {
                lbl_x.Text = e.Location.X.ToString();
                lbl_y.Text = e.Location.Y.ToString();
    
                if (e.Clicks > 0)
                    LogWrite("Mouse - " + e.Button.ToString());
            }
    
            public void MyKeyDown(object sender, KeyEventArgs e)
            {
                LogWrite("KeyDown - " + e.KeyData.ToString());
            }

    Y me los guarda así:

    List1

    Pero lo que quisiera hacer es poder agregar estos valores en el listView donde están las cuatro columnas vacías con los datos de la base de datos:

    img2

    Es decir en lugar de manejar dos listView manejar solo uno ya que necesito almacenar de nuevo estos datos en la base de datos con sus respectivos valores agregados (Mouse or Key, Action, "X" y 1"Y") o de ser posible unir los datos de los dos listView aunque creo esto es mas complicado.

    Con la opción que me comentas creo no es apta para lo que pretendo realizar, creo que solo es modificar el método LogWrite para que almacene los valores en el listView columna 7 row 1 y y así consecutivamente pero no lo he conseguido.

    Creo ya esta mas clara la pregunta alguna sugerencia?


    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.

    viernes, 25 de septiembre de 2020 4:57
  • Hola Dany

    No se si entiendo bien. Si todas las columnas (las 10) se llenan al mismo tiempo, entonces por favor lee bien mi última respuesta y fijate en el link que puse, que en ambos está bien explicado. 

    Si las columnas de la 7 a la 10 se van llenando en tiempo de ejecución (que es lo que no estoy seguro si entendí bien) entonces podes asignarles elementos de la siguiente forma:

    listView1.Items.Add("NombreColumna").SubItems.Add(item);

    Si no es esto, explicame con más detalle qué es lo que se carga antes, y qué en tiempo de ejecución.

    viernes, 25 de septiembre de 2020 15:20
  • Hola Dany

    No se si entiendo bien. Si todas las columnas (las 10) se llenan al mismo tiempo, entonces por favor lee bien mi última respuesta y fijate en el link que puse, que en ambos está bien explicado. 

    Si las columnas de la 7 a la 10 se van llenando en tiempo de ejecución (que es lo que no estoy seguro si entendí bien) entonces podes asignarles elementos de la siguiente forma:

    listView1.Items.Add("NombreColumna").SubItems.Add(item);

    Si no es esto, explicame con más detalle qué es lo que se carga antes, y qué en tiempo de ejecución.

    Anexo imagen lo que esta en azul es lo que carga el ListView desde un inicio con datos del Sql y las columnas 7,8,9 y 10 son las columnas donde debo ingresar valores en tiempo ejecución.

    Resaltadas en amarillo:

    Estas son las columnas que tengo que ir llenando en tiempo ejecución desde el Row 1 columna 7,8,9 y 10.

    img

    El Metodo que guarda los eventos del Mouse o Teclado en el listView que tengo actualmente es este:

    El primer texto es una cadena que separo con un Split e inserto en el Item 0 y 1.

    private void LogWrite(string txt)
            {
                string[] lineItems = txt.Split('-');//Separas la cadena por el carácter '-'
                listCapture.CheckBoxes = true;
                lv = new ListViewItem(txt);  //en un array y obtienes la posición 0
                lv.Text = lineItems[0]; // en un array y obtienes la posición 1
                lv.SubItems.Add(lineItems[1]);
                lv.SubItems.Add(lbl_x.Text.ToString());
                lv.SubItems.Add(lbl_y.Text.ToString());
                listCapture.Items.Add(lv);
                count = count + 1;
                lblItems.Text = "Total events: " + count.ToString();
            }

    Entonces con tu propuesta lo que hace es agregar una nueva linea es decir no comienza a guardar los datos en la columna 7,1 si no va a la ultima fila con datos y agrega una nueva y almacena el valor en la columna 0 y 1 ,ultimafila.

     listData.Items.Add("Mouse or Key").SubItems.Add(Dato1);
                listData.Items.Add("Action").SubItems.Add(Dato2);
                listData.Items.Add("X").SubItems.Add(lbl_x.Text.ToString());
                listData.Items.Add("Y").SubItems.Add(lbl_y.Text.ToString());

    img3

    Espero que este un poco mas claro.

    Estoy tratando de posicionarme en el row1 columna 7 para desde ahi comenzar a insertar datos.

    DS


    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.



    • Editado Dany Solis domingo, 27 de septiembre de 2020 4:31 Agregue mas datos
    domingo, 27 de septiembre de 2020 4:29
  • Hola Dany

    Busqué un poco más, y luego de entender como es la lógica y de un ratito de pruebas, te presento aquí el método SetToColAndRow(). Recibe el índice de la fila en la cual vas a poner el item, el índice de la columna, y el string del item. Lo que hace es, 1° verificar que la fila y la columna existan, caso contrario devuelve false y no hace nada; 2°, si existen la fila y la columna, recolecta todos los items de la fila en un array de string[] y le pone en la columna el valor de item, en las columnas que no hay nada pone un "" (string vacío), luego elimina la fila e inserta en el mismo lugar la misma fila con el nuevo item.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsAppListViewColumns
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                listView1.View = View.Details;
                listView1.FullRowSelect = true;
    
                listView1.Columns.Add("Column 1");
                listView1.Columns.Add("Column 2");
                listView1.Columns.Add("Column 3");
                listView1.Columns.Add("Column 4");
                listView1.Columns.Add("Column 5");
    
                ListViewItem items = new ListViewItem(new string[] { "item 1", "item 2", "item 3" });
                listView1.Items.Add(items);
    
                ListViewItem items2 = new ListViewItem(new string[] { "item 4", "item 5", "item 6" });
                listView1.Items.Add(items2);
    
                ListViewItem items3 = new ListViewItem(new string[] { "item 7", "item 8", "item 9" });
                listView1.Items.Add(items3);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                bool v = SetToColAndRow(4, 1, "item 15");
            }
    
            private bool SetToColAndRow(int colIndex, int rowIndex, string item) 
            {
                int a;
                string[] items;
                
                items = new string[listView1.Columns.Count];
                for (a = 0; a < listView1.Columns.Count; a++) 
                    items[a] = "";
    
                if (listView1.Items.Count <= rowIndex || colIndex >= listView1.Columns.Count)
                    return false;
    
                for (a = 0; a < listView1.Columns.Count; a++) 
                {
                    if (a == colIndex)
                        items[a] = item;
                    else
                    {
                        if (a < listView1.Items[rowIndex].SubItems.Count)
                            items[a] = listView1.Items[rowIndex].SubItems[a].Text;
                        else
                            items[a] = "";
                    }
                }
                listView1.Items.RemoveAt(rowIndex);
                listView1.Items.Insert(rowIndex, new ListViewItem(items));
                return true;
            }
        }
    }
    

    Espero te sea útil.

    Saludos

    Pablo

    domingo, 27 de septiembre de 2020 15:24
  • Gracias una disculpa por contestar tan tarde, probe el codigo e hice algunas modificaciones ligeras y ya me es funcional.

    Te agradezco de antemano el apoyo.

    Saludos

    DS


    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.

    jueves, 1 de octubre de 2020 22:44