Обнаружение переупорядочения столбцов - ColumnDisplayIndexChanged повышается несколько раз - PullRequest
0 голосов
/ 19 декабря 2018

Я работаю над проектом winforms .net 4.6.1 C #, у которого есть сетевое представление, в котором пользователи могут изменять порядок столбцов.

Я хотел бы сохранить новый порядок в таблице базы данных, но у меня возникли проблемы с поиском подходящего события для определения, когда пользователь изменил порядок столбцов.

После поиска я указал на событие DataGridView.ColumnDisplayIndexChanged в этой теме .Но это не решает мою проблему.(он дает решение для нескольких событий, когда вы заполняете представление таблицы данных, но на это легко ответить, добавив обработчик после установки источника данных)

Этот тип работает, но срабатывает несколько раз, когда пользователь меняетпорядок столбцов (например, при изменении столбцов A, B, C, D на D, A, B, C событие запускается 3 раза (вероятно, для A, B, D, C - A, D, B,C - D, A, B, C)

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

Мои вопросы:

  1. Является ли это событие «лучшим» для моего случая?

  2. Если это так, как я могу определить последнее событие ColumnDisplayIndexChanged (D, A, B, C)?

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Когда вы переупорядочиваете столбцы, ColumnDisplayIndexChanged будет повышаться для всех столбцов, чей индекс отображения был изменен.Например, если вы переместите столбец A в положение после C, для всех этих трех столбцов произойдет событие.

Существует решение, позволяющее перехватить последний столбец.DataGridViewColumn имеет внутреннее свойство с именем DisplayIndexHasChanged, которое имеет значение true, если событие должно быть запущено для столбца.Закрытый метод, который вызывает событие, просматривает список столбцов и для каждого столбца, если это свойство имеет значение true, сначала устанавливает его в false, а затем вызывает событие.Вы можете прочитать внутренние реализации здесь .

Вы можете проверить, нет ли столбца, имеющего DisplayIndexHasChanged с истинным значением, вы можете сказать, что это последнее событие в последовательности:

private void dgv_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
    var g = (DataGridView)sender;
    var property = typeof(DataGridViewColumn).GetProperty("DisplayIndexHasChanged",
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    if (g.Columns.Cast<DataGridViewColumn>().Any(x => (bool)property.GetValue(x)))
        return;
    else
        MessageBox.Show("Changed");
}

Имейте в виду, вы должны отключить захват этого события при добавлении столбцов:

private void f_Load(object sender, EventArgs e)
{
    LoadData();
}
void LoadData()
{
    dgv.ColumnDisplayIndexChanged -= dgv_ColumnDisplayIndexChanged;
    dgv.DataSource = null;
    var dt = new DataTable();
    dt.Columns.Add("A");
    dt.Columns.Add("B");
    dt.Columns.Add("C");
    dgv.DataSource = dt;
    dgv.ColumnDisplayIndexChanged += dgv_ColumnDisplayIndexChanged;
}
0 голосов
/ 19 декабря 2018

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

Используя подход с отладкой, вы можете отменить старое событие, если новое событие будет запущено сразу после того, как вы захотите разрешить некоторое время.между вызовами.

Пример: запись в хранилище, только если нет нового события после, скажем, 1 секунды или 5 секунд, в зависимости от того, что приемлемо для вашего приложения

Скажем, мы решили сохранить сотмена 1 секунды

Первое событие происходит, когда вы запускаете действие, которое имеет 1 секунду для выполнения

Если другое событие вызвано, старое действие игнорируется, а новое действие теперь имеет 1 секунду для выполнения ии так далее для других последовательных действий

public static Action Debounce(this Action func, int milliseconds = 300)
{
    var last = 0;
    return arg =>
    {
        var current = Interlocked.Increment(ref last);
        Task.Delay(milliseconds).ContinueWith(task =>
        {
            if (current == last) func(arg);
            task.Dispose();
        });
    };
}

Предполагая следующее действие для сохранения ваших данных ниже. Действие a = (arg) => {сохранить мои данные здесь};

сначала назначьте debouncer дляваше действие

var debouncedWrapper = a.Debounce(1000); //1 sec debounce

Тогда вы можете использовать его следующим образом

public void datagridchangeevent(object sender, Event e)
{
  debouncedWrapper()
}

Это будет игнорировать последовательные вызовы, и действие будетвыполняется только в том случае, если в течение одной секунды ничего не вызывается

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...