Найдите строку в DataGridView, когда связанный DataView отсортирован по другому столбцу в .NET - PullRequest
0 голосов
/ 21 октября 2010

У меня есть DataGridView с DataTable, установленным в его DataSource.DataTable имеет два столбца.У пользователя есть TextBox, который динамически (после каждого нажатия клавиши) ищет совпадение в первом столбце.Я хочу перейти к соответствующей записи (если есть) после каждой записи ключа, поэтому она должна быть быстрой.Я использую метод Find () в DefaultView DataTable.Затем я позиционирую диспетчер валют, который заставляет DataGridView перейти к правильной записи.

Однако все это прерывается, когда пользователь выбирает сортировку по второму столбцу.Это меняет сортировку в DefaultView, и Find () больше не может искать по первому столбцу.

Если я создаю второй DataView, который всегда сортируется по первому столбцу, я всегда могу выполнить Find (), но тогда я не знаю, как идентифицировать соответствующую запись в DataGridView.

Существует ли способ использовать Find () для столбца в DataTable, несмотря на то, что связанный DataView сортируется по другому столбцу, ивсе еще перейти к найденной строке в DataGridView?

Ответы [ 2 ]

0 голосов
/ 18 апреля 2011

Немного проще, если вы используете BindingSource:

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;

public class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    BindingSource source;

    public Form1()
    {
        Controls.Add(new DataGridView { Name = "DGV", Dock = DockStyle.Fill, TabIndex = 2 });
        Controls.Add(new TextBox { Name = "Find", Dock = DockStyle.Top, TabIndex = 1 });

        DataTable table = CreateData();
        source = new BindingSource(table, null);
        (Controls["DGV"] as DataGridView).DataSource = source;
        source.Sort = "First";

        Controls["Find"].TextChanged += (s, e) =>
            {
                int index = source.Find("First", (s as Control).Text);
                if (index >= 0)
                    source.Position = index;
            };
    }

    private DataTable CreateData()
    {
        DataTable table = new DataTable { Columns = { "First", "Second" } };
        foreach (var o in Enumerable.Range('a', 26).Select(ch => new { F = new String((char)ch, 1), S = new String((char)('z' - (ch - 'a')), 1)}))
        {
            DataRow dr = table.NewRow();
            dr[0] = o.F;
            dr[1] = o.S;
            table.Rows.Add(dr);
        };
        return table;
    }
}
0 голосов
/ 17 апреля 2011

Подумайте еще раз о проблеме, когда данные не отсортированы по первому столбцу (даже если это делается с помощью фреймворка). Линейный поиск O (n) лучше всего подходит для вашей проблемы.Используя это, я реализовал следующий демонстрационный код, который решает вашу проблему, просто добавьте DataGridView & TextBox в форму, настройте обработчики событий, вы должны увидеть поведение, которое вы ищете, с помощью приведенного ниже кода.This is not production quality code, rather directon on howto solve your problem in smaller context.

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        /// <summary>
        /// You can optimize this functionality only when the first column is sorted. 
        /// If not there is no faster way other than linear search, even if it would be done by framework, in my opinion linear search is the best posssible solution when the first column is not sorted.
        /// This piece of code is for demo purposes on how to do something, should be refined to fit your production cases.
        /// </summary>
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            string text = textBox1.Text.Trim();
            int index = dataGridView1.CurrentCell.RowIndex;
            CurrencyManager cm = dataGridView1.BindingContext[dataGridView1.DataSource] as CurrencyManager;
            DataView view = cm.List as DataView;

            if (string.IsNullOrEmpty(text)) return;

            //If sorted on first column
            if (view.Sort.Contains("First")) //column will be "[First]"
            {
                index = source.DefaultView.Find(text);
                SetIndex(cm, index);
            }
            //if not
            else if (view.Sort.Contains("Second")) //column will be "[Second]"
            {
                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {
                    if (dataGridView1.Rows[i].Cells["First"].Value.ToString().StartsWith(text))
                    {
                        index = i; break;
                    }
                }
                SetIndex(cm, index);
            }
        }

        private void SetIndex(CurrencyManager cm, int index)
        {
            if (index >= 0 && index < source.Rows.Count)
            {
                cm.Position = index;
            }
        }

        private void CreateData()
        {
            source.Columns.Add("First", typeof(string));
            source.Columns.Add("Second", typeof(string));

            var f = from first in Enumerable.Range('a', 26)
                    select new string(new char[] { (char)first });

            var s = f.Reverse();

            var c1Enumerator = f.GetEnumerator();
            var c2Enumerator = s.GetEnumerator();

            for (int i = 0; i < f.Count(); i++)
            {
                DataRow dr = source.NewRow();
                c1Enumerator.MoveNext();
                c2Enumerator.MoveNext();

                dr[0] = c1Enumerator.Current;
                dr[1] = c2Enumerator.Current;
                source.Rows.Add(dr);
            }
        }

        DataTable source = new DataTable();

        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            CreateData();
            dataGridView1.DataSource = source;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...