web-dev-qa-db-fra.com

DataGridView Selected Row déplacer vers le haut et le bas

Comment puis-je permettre aux lignes sélectionnées dans un DataGridView (DGV) d'être déplacées vers le haut ou le bas? J'ai déjà fait cela avec un ListView. Malheureusement, remplacer le DGV n’est pas une option ( curses ). À propos, la source de données DGV est une collection générique.

Le DGV a deux boutons sur le côté, oui, UP et Down. Quelqu'un peut-il m'aider à me diriger dans la bonne direction? J'ai le code que j'ai utilisé pour le ListView si ça va aider (ça ne m'a pas aidé).

11
Silly Rabbit

Si vous modifiez de manière programmée l'ordre des éléments de votre collection, le DGV doit en tenir compte automatiquement. 

Sloppy, exemple mi-travail:

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

Une partie de cette logique peut être fausse, et cela peut ne pas être l'approche la plus efficace non plus. En outre, il ne prend pas en compte les sélections de plusieurs lignes.

Hmm, une dernière chose, si vous utilisez une liste ou une collection standard, cela ne se passera pas aussi facilement. Lister et Collection ne pas émettre les événements que le DGV trouve utiles pour la liaison de données. Vous pouvez "casser" la liaison de données chaque fois que vous modifiez la collection, mais une meilleure solution consisterait pour vous à utiliser System.ComponentModel.BindingList. Lorsque vous modifiez l'ordre de la BindingList, le fichier DGV doit refléter automatiquement le changement.

6
Yoopergeek

Pour développer la réponse de Yoopergeek, voici ce que j'ai. Je n'utilisais pas de source de données (les données sont en train d'être déposées dans le registre à la fermeture du formulaire et rechargées lors du chargement du formulaire).

Cet exemple empêchera les lignes de se déplacer hors de la grille et sera perdu, et resélectionnera également la cellule dans laquelle se trouvait la personne.

Pour simplifier les choses pour le copier/coller, j'ai modifié afin que vous n'ayez besoin de changer "gridTasks" que par le nom de votre DataGridView, plutôt que de le renommer dans le code.

Cette solution ne fonctionne que pour une seule cellule/ligne sélectionnée.

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 { }
}
27
Para

Cela devrait marcher. J'utilise un BindingSource au lieu de lier ma liste directement au 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; }
    }
8
Jürgen Steinblock

Remplissez d'abord votre datagridview, par exemple, vous avez un tableau avec 3 colonnes

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;

Puis, sur le bouton, cliquez sur

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;
    }
}

Faites la même chose pour le bouton enfoncé, remplacez simplement row index de rowIndex - 1 par rowindex + 1 dans votre méthode buttonDown_Click.

1
Nikola Glisic
   DataGridViewRow BeginingRow = new DataGridViewRow();
   int BeginingRowIndex ;   
        private void DataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.Button != MouseButtons.Left ||e.RowIndex < 0 ) return;
            if (BeginingRowIndex > e.RowIndex)
            {
                DataGridView1.Rows.Insert(e.RowIndex);
                foreach (DataGridViewCell cellules in BeginingRow.Cells)
                {
                    DataGridView1.Rows[e.RowIndex].Cells[cellules.ColumnIndex].Value = cellules.Value;
                }
                DataGridView1.Rows.RemoveAt(BeginingRowIndex + 1);

            }
            else
            {
                DataGridView1.Rows.Insert(e.RowIndex +1);
                foreach (DataGridViewCell cellules in BeginingRow.Cells)
                {
                    DataGridView1.Rows[e.RowIndex+1].Cells[cellules.ColumnIndex].Value = cellules.Value;
                }
                DataGridView1.Rows.RemoveAt(BeginingRowIndex);
            }

            DataGridView1.RowsDefaultCellStyle.ApplyStyle(BeginingRow.DefaultCellStyle);
            DataGridView1.Rows[e.RowIndex].Selected = true;
    }

    private void DataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.Button != MouseButtons.Left ||e.RowIndex < 0 ) return;
                BeginingRowIndex = e.RowIndex;
                BeginingRow = DataGridView1.Rows[BeginingRowIndex];
                BeginingRow.DefaultCellStyle = DataGridView1.Rows[BeginingRowIndex].DefaultCellStyle;
    }
0
user411188

Il y a une manière beaucoup plus simple que la plupart des posts ici (à mon avis). Effectuer l'action pour un clic sur le bouton "up" est fondamentalement juste un échange de lignes avec celle ci-dessus. Si vous contrôlez les valeurs vous-même (comme la question a été posée), il vous suffit d'échanger les valeurs des lignes. Rapide et simple! 

NOTE: cela ne fonctionne que lorsque la sélection multiple est désactivée sur la grille de données! Comme vous pouvez le constater, je ne fais que prêter attention à l'élément de l'index 0 de la collection SelectedRows.

Voici ce que j'ai utilisé: 

    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
        }
    }

Pour effectuer un "clic", vous pouvez également faire le contraire, même logique

0
Matt0

c'est la solution la plus courte que j'ai trouvée au problème et je viens de refactoriser un peu le code trouvé dans: 

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>

et avec le code derrière ...

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();
    }
0
jortizromo

En-tête 3

private void buttonX8_Click (expéditeur d'objet, EventArgs e) // down { DataGridViewX grid = dataGridViewX1; essayer { 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] .Sélections = 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
vahid ghezelvand

solution liée aux données avec prise en charge de la sélection multiple, utilisez SharpDevelop 4.4 pour convertir en 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
stax76
private void butUp_Click(object sender, EventArgs e)
{
    DataTable dtTemp = gridView.DataSource as DataTable;

    object[] arr = dtTemp.Rows[0].ItemArray;
    for (int i = 1; i < dtTemp.Rows.Count; i++)
    {
        dtTemp.Rows[i - 1].ItemArray = dtTemp.Rows[i].ItemArray;
    }
    dtTemp.Rows[dtTemp.Rows.Count - 1].ItemArray = arr;

}
private void butDown_Click(object sender, EventArgs e)
{
    DataTable dtTemp = gridView.DataSource as DataTable;

    object[] arr = dtTemp.Rows[dtTemp.Rows.Count - 1].ItemArray;
    for (int i = dtTemp.Rows.Count - 2; i >= 0; i--)
    {
        dtTemp.Rows[i + 1].ItemArray = dtTemp.Rows[i].ItemArray;
    }
    dtTemp.Rows[0].ItemArray = arr;
}
0
namco

La réponse de SchlaWiener a bien fonctionné, et je veux juste ajouter quelque chose:

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();

}

L'ajout de ces 3 lignes en bas pour déplacer également la sélection (à la fois bindingSource et dataGridView), afin que nous puissions cliquer en permanence sur le bas pour déplacer une ligne vers le haut.

Pour descendre, appelez simplement bs.MoveNext ()

(Je n'ai pas assez de réputation pour poster en commentaire)

0
Yang Chi-En

Je cherchais ce bouton UP/DOWN et je suis heureux d'avoir trouvé ceci. Mieux vaut mettre le bs.RaiseListChangedEvents = fausse déclaration après le retour ou cela ne fonctionne pas tout le temps.

Et en C # 3.0, vous pouvez ajouter deux méthodes d'extension à BindingSource comme ceci:

public static class BindingSourceExtension
{
    public static void MoveUp( this BindingSource aBindingSource )
    {
        int position = aBindingSource.Position;
        if (position == 0) return;  // already at top

        aBindingSource.RaiseListChangedEvents = false;

        object current = aBindingSource.Current;
        aBindingSource.Remove(current);

        position--;

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

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

    public static void MoveDown( this BindingSource aBindingSource )
    {
        int position = aBindingSource.Position;
        if (position == aBindingSource.Count - 1) return;  // already at bottom

        aBindingSource.RaiseListChangedEvents = false;

        object current = aBindingSource.Current;
        aBindingSource.Remove(current);

        position++;

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

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

Enfin un bon usage des méthodes d’extension à la place de tous ces mauvais exemples de String .. ;-)

0
user220630