С# - Как передать данные из dataGridView1 в другой с помощью нажатия кнопки?

У меня есть dataGridView1, dataGridView2 и ButtonAdd в одной форме.

Пользователь будет:

1- выберите любую «Ячейку» или «Весь ряд».

2-выбрать несколько строк

Потом:

выбранные данные будут перемещены из dataGridView1 в dataGridView2 при нажатии кнопки. это все, что мне нужно сделать.

Моя попытка:

Я попробовал это решение после многих поисков, и оно почти готово, но есть небольшая проблема, с которой я не смог справиться:

Полный код:

private const string strconneciton = @"YourConnectionString";
    SqlConnection con = new SqlConnection(strconneciton);
    SqlCommand cmd = new SqlCommand();
    DataTable dataTable;

private void loadDataIntoGridView1()
    {
        try
        {
            con.Open();
            cmd.CommandText = "SELECT id, accNum, accName FROM Employees";
            cmd.Connection = con;

            SqlDataAdapter adapter = new SqlDataAdapter();
            adapter.SelectCommand = cmd;

            dataTable = new DataTable();
            adapter.Fill(dataTable);

            BindingSource bSource = new BindingSource();
            bSource.DataSource = dataTable;
            dataGridView1.DataSource = bSource;

            //i don't know if this line is useful...
            dataGridView2.DataSource = dataTable.Clone();

            adapter.Update(dataTable);
            con.Close();

        }
        catch (Exception ed)
        {
            con.Close();
            MessageBox.Show(ed.Message);
        }
    }//end loadDataIntoGridView1


private void buttonSend_Click(object sender, EventArgs e)
{       
    if (dataGridView1.SelectedCells.Count > 0)
    {
        foreach (DataGridViewCell oneCell in dataGridView1.SelectedCells)
        {
            if (oneCell.Selected)
            {
                //this should add the rows that is selected from dataGridView1 and,
                //pass it to dataGridView2
                var currentRow = ((DataRowView)dataGridView1.CurrentRow.DataBoundItem).Row;
                 ((DataTable)dataGridView2.DataSource).ImportRow(currentRow);

                //this will remove the rows you have selected from dataGridView1
                dataGridView1.Rows.RemoveAt(oneCell.RowIndex);
            }//end if
        }//end foreach
    }//end if
}//end button click

Отладка:

просто Обратите внимание на одну вещь, прежде чем начать:

  • метод удаления строк (несколько или один) работает нормально во всех случаях.
  • проблема заключается в методе добавления в DGV2, я взял его из здесь... он отлично работает при выборе один ряд, а не несколько.

1- если вы выбрали одну ячейку/строку, она будет успешно добавлена ​​и удалена.

2- если вы выбрали несколько строк, скажем, первую и вторую, она добавит вторую и третью, затем определенно удалит их, но добавляется только одна.. почему?!

Потому что здесь

var currentRow = ((DataRowView)dataGridView1.CurrentRow.DataBoundItem).Row;
            ((DataTable)dataGridView2.DataSource).ImportRow(currentRow);   

получает текущий индекс существующих строк в DGV1, выполняет итерацию по количеству выбранных строк и добавляет их в DGV2.

Скриншот:

изображение того, как выполняется процесс: изображение того, как выполняется процесс.

что мне нужно сделать: что мне нужно сделать

Что нужно сделать, чтобы решить эту проблему?


person Mahmoud Ayman    schedule 23.11.2017    source источник
comment
Пробовали ли вы вставить?   -  person k4yaman    schedule 23.11.2017
comment
нет, я думаю, если у вас есть способ описать вставку для решения моей проблемы, я буду признателен.   -  person Mahmoud Ayman    schedule 23.11.2017


Ответы (3)


Хотя Марко прав, право собственности на строку принадлежит таблице как исключению. Чтобы обойти это, вы можете сделать это так...

// создает новую строку на основе таблицы, которую вы собираетесь // вставить в INTO с той же структурой

var copyRow = table.NewRow(); 
copyRow.ItemArray = currentRow.ItemArray;
table.Rows.Add( copyRow );

ItemArray представляет собой список ВСЕХ свойств столбца таблицы в порядке без явной ссылки на Row["someColumn"]. Таким образом, копирование массива в новую строку дает вам все столбцы. Это - при условии, что обе структуры таблиц одинаковы - и, похоже, из предоставленного вами сценария.

Пояснение

Приведенный выше код выполняет только одну строку и будет применяться на основе вашего цикла, в котором

if (oneCell.Selected)

У вас есть несколько столбцов, выбранных для каждой строки, что вызывает некоторую путаницу в ваших циклах. На самом деле вы нажимаете одну и ту же строку несколько раз. В любом случае, я обнаружил, что вы на самом деле делаете это в приложении Windows, а не в WPF. Я создал форму и разместил код ниже.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        loadDataIntoGridView1();
    }

    public DataTable tblFrom { get; set; }
    public DataTable tblTo { get; set; }
    private void loadDataIntoGridView1()
    {
        tblFrom = new DataTable();
        tblFrom.Columns.Add("Col1", typeof(string));
        tblFrom.Columns.Add("Col2", typeof(string));

        tblTo = tblFrom.Clone();

        DataRow tmp;
        while (tblFrom.Rows.Count < 20)
        {
            tmp = tblFrom.NewRow();
            tmp["Col1"] = "my row " + tblFrom.Rows.Count;
            tmp["Col2"] = "testing";
            tblFrom.Rows.Add(tmp);
        } 

        dataGridView1.AutoGenerateColumns = true;
        dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        dataGridView2.AutoGenerateColumns = true;
        dataGridView2.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        dataGridView1.DataSource = tblFrom;
        dataGridView2.DataSource = tblTo;
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
        // if no ROWS selected, get out.
        if (dataGridView1.SelectedRows.Count == 0)
            return;

        foreach( DataGridViewRow vr in dataGridView1.SelectedRows)
        {
            var currentRow = ((DataRowView)vr.DataBoundItem).Row;
            ((DataTable)dataGridView2.DataSource).ImportRow(currentRow);

            //this will remove the rows you have selected from dataGridView1
            dataGridView1.Rows.RemoveAt(vr.Index);
        }
    }
}

Здесь у меня есть форма с двумя сетками, похожими на то, что было у вас, и одна кнопка для «Перемещения» записей (но только в одном направлении), вам нужно будет настроить одно/все/от/к направления.

Несколько изменений. Я изменил сетку, чтобы применить режим выделения ко всей строке. Это предотвратит несколько записей для одной строки только потому, что у вас есть несколько доступных столбцов. Множественный выбор по-прежнему возможен путем перетаскивания между ячейками ИЛИ Ctrl+щелчок по отдельным строкам. Это позволяет выбирать строки за пределами одной и той же видимой области экрана.

Я также только что создал таблицу, чтобы принудительно имитировать 20 строк данных, чтобы не все строки были видны одновременно.

Затем событие щелчка... Если не выбраны СТРОКИ, выходите... Если они ЕСТЬ, прокручивайте, но это делает ОДИН НА СТРОКУ, а не несколько раз, если несколько столбцов. Получите строку данных привязки, импортируйте и удалите...

В противном случае вы были очень близки и не нуждались в массиве копирования. Я думаю, что общая проблема заключалась в том, что выбор режима столбцов несколько раз попадал в одну и ту же запись. После удаления строки 0 для первой ячейки строка 1 стала строкой 0 и, таким образом, скопировала ее, удалила, и теперь вы находитесь вне списка, поскольку осталась только одна запись для обработки. Здесь мы получаем всю строку ОДИН РАЗ, независимо от выбранного столбца в ней.

person DRapp    schedule 28.11.2017
comment
этот код копирует все данные и помещает их в другой DataGridView... на самом деле он не выполняет мою работу. я хочу скопировать только выбранные строки, он получает все строки, даже когда я выбираю одну строку - person Mahmoud Ayman; 28.11.2017
comment
@MahmoudAyman, нет, это делает ТОЛЬКО ОДНУ СТРОКУ на основе любой выбранной строки ... Если у вас есть таблица с 20 столбцами, вместо копирования каждой СТОЛБЦА ItemArray ДЕРЖИТ все 20 элементов, даже если у вас есть 5 фактических строк данных в таблице. - person DRapp; 28.11.2017
comment
, да, я это понимаю... но мне нужно выбрать определенные несколько строк и скопировать их в другой DGV... НЕ ВСЕ СТРОКИ, а только выбранные,... ваш код копирует все строки, но это не то, что мне нужно. Я добавил скриншот того, что мне нужно сделать. если вы протестировали код, пожалуйста, вставьте его сюда, чтобы сделать это правильно. - person Mahmoud Ayman; 29.11.2017
comment
спасибо @DRapp, теперь это работает для меня, очень ценю ваш ответ - person Mahmoud Ayman; 02.12.2017

Вместо

ImportRow(currentRow)

используйте что-то вроде этого:

table.Rows.Add(currentRow);

Дай мне знать, если это работает!

person marco pleimes    schedule 23.11.2017
comment
он выдает исключение: System.ArgumentException: эта строка уже принадлежит другой таблице. - person Mahmoud Ayman; 28.11.2017

Вот полный фрагмент, который делает это. В этом примере я использую 2 BindingList для достижения ваших требований. После того, как пользователь нажмет кнопку, образец скопирует выбранные элементы из dgv1data в dgv2data. Затем он удалит элементы из dgv1data.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

namespace MoveDataBetweenDataGridView_47454256
{
    public partial class Form1 : Form
    {
        static BindingList<dgventry> dgv1data = new BindingList<dgventry>();
        static BindingList<dgventry> dgv2data = new BindingList<dgventry>();
        DataGridView dgv1 = new DataGridView();
        DataGridView dgv2 = new DataGridView();
        Button btn = new Button();

        public Form1()
        {
            InitializeComponent();

            InitOurStuff();
            for (int i = 0; i < 10; i++)
            {
                dgv1data.Add(new MoveDataBetweenDataGridView_47454256.dgventry
                {
                    col1 = $"col1_{i}", col2 = $"col2_{i}", col3 = $"col3_{i}"});
                }

        }

        private void InitOurStuff()
        {
            this.Controls.Add(dgv1);//add the DGV to the form
            dgv1.DataSource = dgv1data;//bind our data to it
            dgv1.Dock = DockStyle.Left;//place the DGV somewhere on the form

            this.Controls.Add(dgv2);//add the DGV to the form
            dgv2.DataSource = dgv2data;//bind out data to it
            dgv2.Dock = DockStyle.Right;//place the DGV somewhere on the form

            this.Controls.Add(btn);//add the Button to the form
            btn.Dock = DockStyle.Bottom;//place the Button somewhere on the form
            btn.Click += Btn_Click;//give the Button a event handler
        }




        private void Btn_Click(object sender, EventArgs e)
        {
            List<int> doneIndices = new List<int>();//this will keep track of the row indices we have dealt with

            if (dgv1.SelectedCells.Count > 0)//if something is selected
            {
                foreach (DataGridViewCell item in dgv1.SelectedCells)//loop through the selected cells
                {
                    if (!doneIndices.Contains(item.OwningRow.Index))//if this cell does not belong to a row index we already processed
                    {
                        //we haven't done this row yet
                        dgv2data.Add((dgventry)item.OwningRow.DataBoundItem);//add the DataBoundItem to the other DGV data
                        doneIndices.Add(item.OwningRow.Index);//put the current row index in our tracking list
                    }
                    else
                    {
                        //we have done this row already, move on to the next one
                        continue;
                    }
                }
            }

            //remove all the duplicate entries
            foreach (dgventry item in dgv2data)
            {
                dgv1data.Remove(item);
            }
        }
    }



    public class dgventry
    {
        public string col1 { get; set; }
        public string col2 { get; set; }
        public string col3 { get; set; }

    }
}
person blaze_125    schedule 29.11.2017