DataGridView выбранных строк двигаться вверх и вниз - PullRequest
11 голосов
/ 18 июня 2009

Как разрешить перемещение выбранных строк в DataGridView (DGV) вверх или вниз. Я сделал это раньше с ListView. К сожалению, для меня замена DGV не вариант ( curses ). Кстати, источник данных DGV - это универсальная коллекция.

DGV имеет две кнопки сбоку, да, вверх и вниз. Может ли кто-нибудь помочь направить меня в правильном направлении. У меня есть код, который я использовал для ListView, если это поможет (мне это не помогло).

Ответы [ 13 ]

29 голосов
/ 29 марта 2012

Просто чтобы расширить ответ Йуперджика, вот что у меня есть. Я не использовал источник данных (данные сбрасываются в реестр при закрытии формы и перезагружаются при загрузке формы)

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

Чтобы упростить процесс копирования / вставки, я изменил его, поэтому вам нужно всего лишь заменить "gridTasks" на имя вашего DataGridView, а не переименовывать его по всему коду.

Это решение работает только для выбранной ячейки / строки.

private void btnUp_Click(object sender, EventArgs e)
{
    DataGridView dgv = gridTasks;
    try
    {
        int totalRows = dgv.Rows.Count;
        // get index of the row for the selected cell
        int rowIndex = dgv.SelectedCells[ 0 ].OwningRow.Index;
        if ( rowIndex == 0 )
            return;
        // get index of the column for the selected cell
        int colIndex = dgv.SelectedCells[ 0 ].OwningColumn.Index;
        DataGridViewRow selectedRow = dgv.Rows[ rowIndex ];
        dgv.Rows.Remove( selectedRow );
        dgv.Rows.Insert( rowIndex - 1, selectedRow );
        dgv.ClearSelection();
        dgv.Rows[ rowIndex - 1 ].Cells[ colIndex ].Selected = true;
    }
    catch { }
}

private void btnDown_Click(object sender, EventArgs e)
{
    DataGridView dgv = gridTasks;
    try
    {
        int totalRows = dgv.Rows.Count;
        // get index of the row for the selected cell
        int rowIndex = dgv.SelectedCells[ 0 ].OwningRow.Index;
        if ( rowIndex == totalRows - 1 )
            return;
        // get index of the column for the selected cell
        int colIndex = dgv.SelectedCells[ 0 ].OwningColumn.Index;
        DataGridViewRow selectedRow = dgv.Rows[ rowIndex ];
        dgv.Rows.Remove( selectedRow );
        dgv.Rows.Insert( rowIndex + 1, selectedRow );
        dgv.ClearSelection();
        dgv.Rows[ rowIndex + 1 ].Cells[ colIndex ].Selected = true; 
    }
    catch { }
}
9 голосов
/ 18 июня 2009

Это должно работать. Я использую BindingSource вместо привязки моего списка непосредственно к DataGridView:

    private List<MyItem> items = new List<MyItem> {
        new MyItem {Id = 0, Name = "Hello"},
        new MyItem {Id = 1, Name = "World"},
        new MyItem {Id = 2, Name = "Foo"},
        new MyItem {Id = 3, Name = "Bar"},
        new MyItem {Id = 4, Name = "Scott"},
        new MyItem {Id = 5, Name = "Tiger"},
    };

    private BindingSource bs;
    private void Form1_Load(object sender, EventArgs e)
    {
        bs = new BindingSource(items, string.Empty);
        dataGridView1.DataSource = bs;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (bs.Count <= 1) return; // one or zero elements

        int position = bs.Position;
        if (position <= 0) return;  // already at top

        bs.RaiseListChangedEvents = false;

        MyItem current = (MyItem)bs.Current;
        bs.Remove(current);

        position--;

        bs.Insert(position, current);
        bs.Position = position;

        bs.RaiseListChangedEvents = true;
        bs.ResetBindings(false);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        if (bs.Count <= 1) return; // one or zero elements

        int position = bs.Position;
        if (position == bs.Count - 1) return;  // already at bottom

        bs.RaiseListChangedEvents = false;

        MyItem current = (MyItem)bs.Current;
        bs.Remove(current);

        position++;

        bs.Insert(position, current);
        bs.Position = position;

        bs.RaiseListChangedEvents = true;
        bs.ResetBindings(false);
    }

    public class MyItem
    {
        public int Id { get; set; }
        public String Name { get; set; }
    }
6 голосов
/ 18 июня 2009

Если вы программно изменяете порядок элементов в вашей коллекции, DGV должен это отражать автоматически.

Небрежный, наполовину рабочий пример:

List<MyObj> foo = DGV.DataSource;
int idx = DGV.SelectedRows[0].Index;
int value = foo[idx];
foo.Remove(value);
foo.InsertAt(idx+1, value)

Часть этой логики может быть неправильной, и это может быть не самым эффективным подходом. Кроме того, он не учитывает выбор нескольких строк.

Хм, последнее: если вы используете стандартный список или коллекцию, все будет не так гладко. Список и коллекция по неэмитентным событиям, которые DGV находит полезными для привязки данных. Вы можете «отрыть» привязку данных при каждом изменении коллекции, но лучшим решением будет использование System.ComponentModel.BindingList. Когда вы меняете порядок в BindingList, DGV должен автоматически отражать это изменение.

1 голос
/ 03 июля 2018

Сначала заполните свое представление данных, например, вы получили таблицу с 3 столбцами

DataTable table = new DataTable();
table.Columns.Add("col1");
table.Columns.Add("col2");
table.Columns.Add("col3");
foreach (var i in yourTablesource(db,list,etc))
{
  table.Rows.Add(i.col1, i.col2, i.col2);
}
datagridview1.DataSource = table;

Затем, при нажатии кнопки вверх

int rowIndex;
private void btnUp_Click(object sender, EventArgs e)
{
    rowIndex = datagridview1.SelectedCells[0].OwningRow.Index;
    DataRow row = table.NewRow();
    row[0] = datagridview1.Rows[rowIndex].Cells[0].Value.ToString();
    row[1] = datagridview1.Rows[rowIndex].Cells[1].Value.ToString();
    row[2] = datagridview1.Rows[rowIndex].Cells[2].Value.ToString();
    if (rowIndex > 0)
    {
        table.Rows.RemoveAt(rowIndex);
        table.Rows.InsertAt(row, rowIndex - 1);
        datagridview1.ClearSelection();
        datagridview1.Rows[rowIndex - 1].Selected = true;
    }
}

Сделайте то же самое для кнопки вниз, просто измените row index с rowIndex - 1 на rowindex + 1 в вашем buttonDown_Click методе

0 голосов
/ 14 сентября 2018

Существует гораздо более простой способ, чем большинство постов здесь (на мой взгляд). Выполнение действия для нажатия кнопки «вверх» - это, по сути, просто замена строк на предыдущую. Если вы сами контролируете значения (как был задан вопрос), вам просто нужно поменять местами значения строк. Быстро и просто!

ПРИМЕЧАНИЕ: это работает, только если в сетке данных отключен множественный выбор! Как вы можете заметить, я обращаю внимание только на элемент с индексом 0 в коллекции SelectedRows.

Вот что я использовал:

    private void btnUp_Click(object sender, EventArgs e)
    {
        var row = dgvExportLocations.SelectedRows[0];

        if (row != null && row.Index > 0)
        {
            var swapRow = dgvExportLocations.Rows[row.Index - 1];
            object[] values = new object[swapRow.Cells.Count];

            foreach (DataGridViewCell cell in swapRow.Cells)
            {
                values[cell.ColumnIndex] = cell.Value;
                cell.Value = row.Cells[cell.ColumnIndex].Value;
            }

            foreach (DataGridViewCell cell in row.Cells)
                cell.Value = values[cell.ColumnIndex];

            dgvExportLocations.Rows[row.Index - 1].Selected = true;//have the selection follow the moving cell
        }
    }

Чтобы выполнить щелчок «вниз», вы можете сделать и обратное, та же логика

0 голосов
/ 10 июня 2015

решение с привязкой к данным с поддержкой множественного выбора, используйте SharpDevelop 4.4 для преобразования в C #.

<Extension()>
Sub MoveSelectionUp(dgv As DataGridView)
    If dgv.CurrentCell Is Nothing Then Exit Sub
    dgv.CurrentCell.OwningRow.Selected = True
    Dim items = DirectCast(dgv.DataSource, BindingSource).List
    Dim selectedIndices = dgv.SelectedRows.Cast(Of DataGridViewRow).Select(Function(row) row.Index).Sort
    Dim indexAbove = selectedIndices(0) - 1
    If indexAbove = -1 Then Exit Sub
    Dim itemAbove = items(indexAbove)
    items.RemoveAt(indexAbove)
    Dim indexLastItem = selectedIndices(selectedIndices.Count - 1)

    If indexLastItem = items.Count Then
        items.Add(itemAbove)
    Else
        items.Insert(indexLastItem + 1, itemAbove)
    End If
End Sub

<Extension()>
Sub MoveSelectionDown(dgv As DataGridView)
    If dgv.CurrentCell Is Nothing Then Exit Sub
    dgv.CurrentCell.OwningRow.Selected = True
    Dim items = DirectCast(dgv.DataSource, BindingSource).List
    Dim selectedIndices = dgv.SelectedRows.Cast(Of DataGridViewRow).Select(Function(row) row.Index).Sort
    Dim indexBelow = selectedIndices(selectedIndices.Count - 1) + 1
    If indexBelow >= items.Count Then Exit Sub
    Dim itemBelow = items(indexBelow)
    items.RemoveAt(indexBelow)
    Dim indexAbove = selectedIndices(0) - 1
    items.Insert(indexAbove + 1, itemBelow)
End Sub
0 голосов
/ 29 апреля 2015

Ответ SchlaWiener сработал хорошо, и я просто хочу кое-что добавить к нему:

private void button1_Click(object sender, EventArgs e) //The button to move up
{
    int position = bs.Position;

    //.......neglected.......

    dataGridView1.ClearSelection();
    dataGridView1.Rows[position].Selected = true;
    bs.MovePrevious();

}

Добавление этих трех строк внизу также для перемещения выделения (и bindingSource, и dataGridView), чтобы мы могли непрерывно щелкать по нижней части для перемещения строки вверх.

Для перехода вниз просто вызовите bs.MoveNext ()

(у меня недостаточно репутации, чтобы оставлять комментарии)

0 голосов
/ 05 октября 2014

Заголовок 3

private void buttonX8_Click (отправитель объекта, EventArgs e) // вниз { DataGridViewX grid = dataGridViewX1; пытаться { int totalRows = grid.Rows.Count; int idx = grid.SelectedCells [0] .OwningRow.Index; if (idx == totalRows - 1) вернуть; int col = grid.SelectedCells [0] .OwningColumn.Index; DataGridViewRowCollection columns = grid.Rows; DataGridViewRow row = row [idx]; rows.Remove (строка); rows.Insert (idx + 1, row); grid.ClearSelection (); grid.Rows [idx + 1] .Cells [col] .Selected = true;

      private void buttonX8_Click(object sender, EventArgs e)//down
    {
        DataGridViewX grid = dataGridViewX1;
        try
        {
            int totalRows = grid.Rows.Count;
            int idx = grid.SelectedCells[0].OwningRow.Index;
            if (idx == totalRows - 1 )
                return;
            int col = grid.SelectedCells[0].OwningColumn.Index;
            DataGridViewRowCollection rows = grid.Rows;
            DataGridViewRow row = rows[idx];
            rows.Remove(row);
            rows.Insert(idx + 1, row);
            grid.ClearSelection();
            grid.Rows[idx + 1].Cells[col].Selected = true;

        }
        catch { }
    }
0 голосов
/ 05 октября 2014

Попробуйте это:

    private void buttonX9_Click(object sender, EventArgs e)//up
    {

        DataGridViewX grid = dataGridViewX1;
        try
        {
            int totalRows = grid.Rows.Count;
            int idx = grid.SelectedCells[0].OwningRow.Index;
            if (idx == 0)
                return;
            int col = grid.SelectedCells[0].OwningColumn.Index;
            DataGridViewRowCollection rows = grid.Rows;
            DataGridViewRow row = rows[idx];
            rows.Remove(row);
            rows.Insert(idx - 1, row);
            grid.ClearSelection();
            grid.Rows[idx - 1].Cells[col].Selected = true;

        }
        catch { }

    }
0 голосов
/ 27 июня 2013

это самое короткое решение проблемы, которое я нашел, и я просто немного изменил код, найденный в:

http://dotnetspeaks.net/post/Moving-GridView-Rows-Up-Down-in-a-GridView-Control.aspx

<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" Font-Names="Verdana" Font-Size="9pt" runat="server" OnRowCreated="GridView1_RowCreated"
    AutoGenerateColumns="False" CellPadding="4" BorderColor="#507CD1" BorderStyle="Solid">
    <Columns>
        <asp:TemplateField HeaderText="First Name">
            <ItemTemplate>
                <asp:Label ID="txtFirstName" runat="server" Text='<%# Eval("FirstName") %>' />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <AlternatingRowStyle BackColor="White" />
</asp:GridView>

<asp:Button ID="btnUp" runat="server" Text="Up" OnClick="btnUp_Click"/>
<asp:Button ID="btnDown" runat="server" Text="Down"  OnClick="btnDown_Click" />
</form>

и с кодом позади ...

public int SelectedRowIndex { get; set; }


    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //Test Records  
            GridView1.DataSource = Enumerable.Range(1, 5).Select(a => new
            {
                FirstName = String.Format("First Name {0}", a),
                LastName = String.Format("Last Name {0}", a),
            });
            GridView1.DataBind();
        }  
    }

    protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            e.Row.Attributes["onmouseover"] = "this.style.cursor='pointer'";
            e.Row.ToolTip = "Click to select row";
            e.Row.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(GridView1, "Select$" + e.Row.RowIndex);
        }
    }


    protected void btnUp_Click(object sender, EventArgs e)
    {
        var rows = GridView1.Rows.Cast<GridViewRow>().Where(a => a != GridView1.SelectedRow).ToList();
        //If First Item, insert at end (rotating positions)  
        if (GridView1.SelectedRow.RowIndex.Equals(0))
        {
            rows.Add(GridView1.SelectedRow);
            SelectedRowIndex = GridView1.Rows.Count -1;
        }
        else
        {
            SelectedRowIndex = GridView1.SelectedRow.RowIndex - 1;
            rows.Insert(GridView1.SelectedRow.RowIndex - 1, GridView1.SelectedRow);
        }
        RebindGrid(rows);
    }

    protected void btnDown_Click(object sender, EventArgs e)
    {
        var rows = GridView1.Rows.Cast<GridViewRow>().Where(a => a != GridView1.SelectedRow).ToList();
        //If Last Item, insert at beginning (rotating positions)  
        if (GridView1.SelectedRow.RowIndex.Equals(GridView1.Rows.Count - 1))
        {
            rows.Insert(0, GridView1.SelectedRow);
            SelectedRowIndex = 0;
        }
        else
        {
            SelectedRowIndex = GridView1.SelectedRow.RowIndex + 1;
            rows.Insert(GridView1.SelectedRow.RowIndex + 1, GridView1.SelectedRow);
        }
        RebindGrid(rows);
    }

    private void RebindGrid(IEnumerable<GridViewRow> rows)
    {
        GridView1.DataSource = rows.Select(a => new
        {
            FirstName = ((Label)a.FindControl("txtFirstName")).Text,
        }).ToList();

        GridView1.SelectedIndex = SelectedRowIndex;
        GridView1.DataBind();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...