C# DataGridViewRow. Отображается ошибка для первой строки? - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть форма, в которой некоторые элементы управления обновляются в соответствии с текущими отображаемыми строками (и их позициями) в DataGridView. Таким образом, внутри события dataGridView1.VerticalScrollBar.ValueChanged я перебираю все строки и проверяю, отображаются они или нет.

Итак, вот проблема при прокрутке вверх (с помощью колесика мыши):

  • dataGridView1.VerticalScrollBar.Value is 0 -> OK
  • dataGridView1.FirstDisplayedCell.RowIndex is 0 -> OK
  • dataGridView1.FirstDisplayedScrollingRowIndex is 0 -> OK
  • dataGridView1.Rows[0].Displayed все еще false -> а?
  • dataGridView1.GetRowDisplayRectangle(0, false) также {0,0,0,0} -> ...?

После проверки https://referencesource.microsoft.com , Я понял, что FirstDisplayedCell на самом деле использует this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen), что кажется неправильным или я не прав? Как это исправить, чтобы получить правильную отображаемую информацию / прямоугольник первой строки?

Заранее спасибо!

Код:

public partial class Form1 : Form
{
    private List<Person> persons = new List<Person>()
    {
        {new Person("mike", 20) },
        {new Person("tim", 31) },
        {new Person("steven", 15) },
        {new Person("dave", 41) },
        {new Person("tom", 35) },
        {new Person("bob", 18) },
        {new Person("peter", 22) },
        {new Person("sarah", 55) },
        {new Person("robert", 69) },
        {new Person("andre", 23) },
    };
    public Form1()
    {
        this.InitializeComponent();
        this.dataGridView1.DataSource = new BindingSource(this.persons, null);

        if (typeof(DataGridView).GetProperty("VerticalScrollBar", BindingFlags.Instance | BindingFlags.NonPublic) is PropertyInfo pi &&
             pi.GetValue(this.dataGridView1, null) is ScrollBar sb)
        {
            sb.ValueChanged += this.Sb_ValueChanged;
        }
    }

    private void Sb_ValueChanged(object sender, EventArgs e)
    {
        int scrollValue = (sender as ScrollBar).Value;
        int index = this.dataGridView1.FirstDisplayedCell.RowIndex;
        int index2 = this.dataGridView1.FirstDisplayedScrollingRowIndex;
        DataGridViewRow row = this.dataGridView1.Rows[index];
        bool displayed = row.Displayed;
        Rectangle rect = this.dataGridView1.GetRowDisplayRectangle(index, false);
    }
}

1 Ответ

1 голос
/ 01 апреля 2020

Похоже, что состояние DataGridViewRow не обновляется, пока не закончится обработка события прокрутки. Вот почему свойство DataGridViewRow.Displayed отображает значение false при прокрутке вверх, чтобы показать ранее не отображаемую строку.

Вы можете использовать небольшую рубку, чтобы поставить в очередь метод, запускаемый сразу после завершения события прокрутки, используя Control.BeginInvoke .

Также нет причин использовать Reflection для взлома DataGridView's VerticalScrollBar. Вместо этого используйте DataGridView.Scroll Event .

Ниже приведена модификация вашего кода для использования события DataGridView.Scroll и BeginInvoke для отображения состояния строки и отображения значений прямоугольника, полученных в пределах прокрутки. событие и сразу после события.

private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
    if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
    {
        int scrollValue = e.NewValue;
        int index = this.dataGridView1.FirstDisplayedCell.RowIndex;
        int index2 = this.dataGridView1.FirstDisplayedScrollingRowIndex;
        DataGridViewRow row = this.dataGridView1.Rows[index];
        bool displayed = row.Displayed;
        Rectangle rect = this.dataGridView1.GetRowDisplayRectangle(index, false);

        Debug.WriteLine($"Scroll: index={index}, rect={rect}, state = {row.GetState(index)}");

        BeginInvoke(new Action(() =>
        {
            Rectangle r = dataGridView1.GetRowDisplayRectangle(index, false);
            Debug.WriteLine($"Invoked: index={index}, rect={r}, state = {row.GetState(index)}");
        }), null);
    }
}
...