none
WinForm中,dataGridView选中行SelectedRows的顺序问题? RRS feed

  • 问题

  • 当我在使用dataGridView的时候,需要用到SelectedRows来获取选中行,但是当我通过SelectedRows[i].Cells[0].value获取数据的时候,发觉数据的顺序是乱的,请问大家碰到过这样的问题没有?

     

     

    例如dataGridView的数据为:

    1

    2

    3

    4

    5

     

    当我全选所有行的时候,当我获取SelectedRows[0].Cells[0].value时,应该是1,这时候却是5,后来通过遍历,发现是反的;

    然后我试过从上往下选取和从下往上选取,其结果一样,难道是SelectedRows默认顺序是反的吗?

    2011年10月13日 9:35

答案

  • Hello——

    我做了实验,好像是的。

    【原因】

    反编译DataGridView的SelectedRows,看到以下代码:

    [Browsable(false)]
    public DataGridViewSelectedRowCollection SelectedRows
    {
        get
        {
            int num;
            IEnumerator enumerator;
            IDisposable disposable;
            DataGridViewSelectedRowCollection dataGridViewSelectedRowCollections = new DataGridViewSelectedRowCollection();
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.CellSelect:
                {
                    return dataGridViewSelectedRowCollections;
                }
                case DataGridViewSelectionMode.FullRowSelect:
                {
                    enumerator = this.selectedBandIndexes.GetEnumerator();
                    try
                    {
                        while (enumerator.MoveNext())
                        {
                            num = (int)enumerator.Current;
                            dataGridViewSelectedRowCollections.Add(this.Rows[num]);
                        }
                    }
                    finally
                    {
                        disposable = enumerator as IDisposable;
                        if (disposable != null)
                        {
                            disposable.Dispose();
                        }
                    }
                }
            }
        }
    }

    既然顺序是反的,说明肯定这个enumerator是反的,继续跟踪反编译:

    这个SelectedBandIndexes是一个“DataGridViewIntLinkedList”类,跟踪:

    internal class DataGridViewIntLinkedList : IEnumerable
    {
        …………………………//无关代码略去

        public int Item
        {
            get   //注意以下部分是反序的!
            {
                if (this.lastAccessedIndex == -1 || index < this.lastAccessedIndex)
                {
                    DataGridViewIntLinkedListElement next = this.headElement;
                    for (int i = index; i > 0; i--)
                    {
                        next = next.Next;
                    }
                    this.lastAccessedElement = next;
                    this.lastAccessedIndex = index;
                    return next.Int;
                }
                do
                {
                    this.lastAccessedElement = this.lastAccessedElement.Next;
                    this.lastAccessedIndex = this.lastAccessedIndex + 1;
                }
                while (this.lastAccessedIndex < index);
                return this.lastAccessedElement.Int;
            }
            set
            {
                if (index != this.lastAccessedIndex)
                {
                    this[index];
                }
                this.lastAccessedElement.Int = value;
            }
        }

    解决方法:再倒置一遍就可以了

    namespace WinFormCSharp
    {
       

        public partial class Form1 : Form
        {


            public Form1()
            {
                InitializeComponent();
            }

            private void Form1_Load(object senderEventArgs e)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("Id"typeof(int));

                for (int i = 1i < 6i++)
                {
                    dt.Rows.Add(i);
                }

                dataGridView1.DataSource = dt;
               
            }

            private void button1_Click(object senderEventArgs e)
            {
                IEnumerable<DataGridViewRow> rows = dataGridView1.SelectedRows.Cast<DataGridViewRow>();
                DataGridViewRow[] Rows = rows.ToArray();
                Array.Reverse(Rows); //对颠倒的行再次颠倒

                foreach (DataGridViewRow item in Rows)
                {
                    MessageBox.Show(item.Cells[0].Value.ToString());
                }
                
            }

           

           

        }
    }

    如果你有其它意见或私下交流,请直接发送maledong_work@foxmail.com;或者讨论(Talk)
    If you do not have QQ, please open the page and download it and click the image to talk or leave message for me.
    下载MSDN桌面工具(Vista,Win7)
    下载Technet桌面小工具(Vista,Win7)
    慈善点击,点击此处
    2011年10月14日 8:19
    版主
  • 备注

    不能保证集合中行的顺序与行被选定的顺序相匹配。

    http://msdn.microsoft.com/zh-cn/library/a1w9zacz(v=VS.80).aspx

    最好是像MSDN那样用DataGridView1.SelectedRows.Contains判断是否选中

    http://msdn.microsoft.com/zh-cn/library/tsktw7a1(VS.80).aspx

     

     


    http://feiyun0112.cnblogs.com/
    2011年10月17日 1:57
    版主

全部回复

  • Hello——

    我做了实验,好像是的。

    【原因】

    反编译DataGridView的SelectedRows,看到以下代码:

    [Browsable(false)]
    public DataGridViewSelectedRowCollection SelectedRows
    {
        get
        {
            int num;
            IEnumerator enumerator;
            IDisposable disposable;
            DataGridViewSelectedRowCollection dataGridViewSelectedRowCollections = new DataGridViewSelectedRowCollection();
            switch (this.SelectionMode)
            {
                case DataGridViewSelectionMode.CellSelect:
                {
                    return dataGridViewSelectedRowCollections;
                }
                case DataGridViewSelectionMode.FullRowSelect:
                {
                    enumerator = this.selectedBandIndexes.GetEnumerator();
                    try
                    {
                        while (enumerator.MoveNext())
                        {
                            num = (int)enumerator.Current;
                            dataGridViewSelectedRowCollections.Add(this.Rows[num]);
                        }
                    }
                    finally
                    {
                        disposable = enumerator as IDisposable;
                        if (disposable != null)
                        {
                            disposable.Dispose();
                        }
                    }
                }
            }
        }
    }

    既然顺序是反的,说明肯定这个enumerator是反的,继续跟踪反编译:

    这个SelectedBandIndexes是一个“DataGridViewIntLinkedList”类,跟踪:

    internal class DataGridViewIntLinkedList : IEnumerable
    {
        …………………………//无关代码略去

        public int Item
        {
            get   //注意以下部分是反序的!
            {
                if (this.lastAccessedIndex == -1 || index < this.lastAccessedIndex)
                {
                    DataGridViewIntLinkedListElement next = this.headElement;
                    for (int i = index; i > 0; i--)
                    {
                        next = next.Next;
                    }
                    this.lastAccessedElement = next;
                    this.lastAccessedIndex = index;
                    return next.Int;
                }
                do
                {
                    this.lastAccessedElement = this.lastAccessedElement.Next;
                    this.lastAccessedIndex = this.lastAccessedIndex + 1;
                }
                while (this.lastAccessedIndex < index);
                return this.lastAccessedElement.Int;
            }
            set
            {
                if (index != this.lastAccessedIndex)
                {
                    this[index];
                }
                this.lastAccessedElement.Int = value;
            }
        }

    解决方法:再倒置一遍就可以了

    namespace WinFormCSharp
    {
       

        public partial class Form1 : Form
        {


            public Form1()
            {
                InitializeComponent();
            }

            private void Form1_Load(object senderEventArgs e)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("Id"typeof(int));

                for (int i = 1i < 6i++)
                {
                    dt.Rows.Add(i);
                }

                dataGridView1.DataSource = dt;
               
            }

            private void button1_Click(object senderEventArgs e)
            {
                IEnumerable<DataGridViewRow> rows = dataGridView1.SelectedRows.Cast<DataGridViewRow>();
                DataGridViewRow[] Rows = rows.ToArray();
                Array.Reverse(Rows); //对颠倒的行再次颠倒

                foreach (DataGridViewRow item in Rows)
                {
                    MessageBox.Show(item.Cells[0].Value.ToString());
                }
                
            }

           

           

        }
    }

    如果你有其它意见或私下交流,请直接发送maledong_work@foxmail.com;或者讨论(Talk)
    If you do not have QQ, please open the page and download it and click the image to talk or leave message for me.
    下载MSDN桌面工具(Vista,Win7)
    下载Technet桌面小工具(Vista,Win7)
    慈善点击,点击此处
    2011年10月14日 8:19
    版主
  • dear

    1.感谢Wei_Dong的分享

    2.如果你的dataGridView有资料绑定来源,建议你从来源做修改不要直接操作dataridView,因未有可能你参考的来源已经变了,只是DataGridView没更新

    http://www.dotblogs.com.tw/yc421206/archive/2011/04/19/23072.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年10月14日 8:30
  • 备注

    不能保证集合中行的顺序与行被选定的顺序相匹配。

    http://msdn.microsoft.com/zh-cn/library/a1w9zacz(v=VS.80).aspx

    最好是像MSDN那样用DataGridView1.SelectedRows.Contains判断是否选中

    http://msdn.microsoft.com/zh-cn/library/tsktw7a1(VS.80).aspx

     

     


    http://feiyun0112.cnblogs.com/
    2011年10月17日 1:57
    版主
  • 高手呀,不过其实要颠倒过来用for循环颠倒不是更容易吗

    2012年3月13日 7:38