Проблема события DevExpress XtraGrid FocusedRowChanged при изменении источника данных - PullRequest
3 голосов
/ 05 мая 2011

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

ВОПРОС: Есть ли способ заставить XtraGrid "забыть" текущееиндекс выделенной строки перед тем, как новый (другой) источник данных будет присвоен сетке?

ПРЕДПОСЫЛКИ Мы используем XtraGrid в качестве своего рода контроллера для того, что отображается на другой панели многопанельной Winform.

Теперь представьте гипотетический сценарий, в котором источник данных XtraGrid постоянно меняется в соответствии с выбором меню.Пункт меню 1 заполняет сетку списком сегодняшних блюд в кафетерии: Id, Name.Пункт меню 2 заполняет сетку списком клиентов, которым пользователь должен позвонить в этот день: ID, имя.Важно то, что это отдельные отдельные источники данных, и источник данных сетки назначается и переназначается.

КРИТИЧЕСКИЙ ФАКТ ДЛЯ ЭТОГО ВОПРОСА: Мы хотим, чтобы событие сетки FocusedRowChanged было единственное место , гдемы задерживаем выбор пользователя в сетке контроллера.Мы магазин "без спагетти кода".FocusedRowChanged лучше, чем событие щелчка, потому что он также обрабатывает навигацию с клавиатуры.Строка с фокусом содержит идентификатор подробной записи, которую нам нужно извлечь из базы данных для отображения на панели # 2.Это работает - большую часть времени .

Вот как это не работает: допустим, в определенный день список клиентов, с которыми пользователь должен связаться, содержит только одну строку.Таким образом, первая (и единственная) строка в сетке - это сфокусированная строка.Теперь предположим, что пользователь подходит к меню и выбирает пункт меню, чтобы отобразить закуски в кафетерии дня.Когда пользователь щелкает по первому элементу в списке записей, событие FocusedRowChanged НЕ запускается, поскольку сетка сохранила память индекса фокусированной строки из предыдущего источника данных.Сфокусированный ряд index не изменился.И поэтому выбор пользователя ничего не вызывает.

Я пытался заставить DevExpress предложить второй более объектно-ориентированный режим (в отличие от подхода, ориентированного на индекс строки), в соответствии с которым каждая строка в сеткебудет иметь GUID, и событие FocusedRowChanged будет срабатывать всякий раз, когда GUID текущей фокусированной строки отличается от GUID ранее сфокусированной строки, независимо от того, совпадает ли индекс фокусированной строки.Это позволило бы динамические изменения источника данных и включить желаемое поведение.Но они отказались.

Поэтому я снова задам свой вопрос: есть ли способ заставить XtraGrid «забыть» текущий фокусированный индекс строки, прежде чем новый источник данных будет присвоен сетке?

Ответы [ 4 ]

3 голосов
/ 13 мая 2011

Тим, у меня была точно такая же проблема, когда в сетке была только одна строка данных, а затем менялись источники данных. Я решил это, установив gridview.FocusedRowHandle = -1 после установки нового источника данных.

1 голос
/ 19 июня 2017

В аналогичной ситуации я подписываюсь на

FocusedRowObjectChanged

событие (с использованием DevExpress 16.1).

0 голосов
/ 04 ноября 2011

Вы можете подписаться на событие DataSourceChanged, которое будет срабатывать при изменении источника данных (как вы уже догадались!), Чтобы затем вы могли использовать GetFocusedObject () объект и отображать соответствующие элементы для другой сетки ...

0 голосов
/ 06 мая 2011

Я думаю, что лучшим решением этой проблемы является создание нового объекта GridView и переопределение его метода DoChangeFocusedRowInternal.Ниже вы найдете стандартную реализацию этого метода.Все, что вам нужно сделать, это изменить помеченную строку так, как диктуют ваши потребности.Кроме того, взгляните на Как создать класс-потомок GridView и зарегистрируйте его для использования во время разработки , статья содержит некоторую полезную информацию.

public class MyGridView : GridView {
        protected override void DoChangeFocusedRowInternal(int newRowHandle, bool updateCurrentRow) {
            if(this.lockFocusedRowChange != 0) return;
            if(!IsValidRowHandle(newRowHandle))
                newRowHandle = DevExpress.Data.DataController.InvalidRow;
            if(FocusedRowHandle == newRowHandle) return; // <<<<<<
            int currentRowHandle = FocusedRowHandle;
            BeginLockFocusedRowChange();
            try {
                DoChangeFocusedRow(FocusedRowHandle, newRowHandle, updateCurrentRow);
            }
            finally {
                EndLockFocusedRowChange();
            }
            RaiseFocusedRowChanged(currentRowHandle, newRowHandle);
        }
    }

ОБНОВЛЕНИЕ

Мой код:

namespace MyXtraGrid {

        public class MyGridControl : GridControl {
            protected override BaseView CreateDefaultView() {
                return CreateView("MyGridView");
            }
            protected override void RegisterAvailableViewsCore(InfoCollection collection) {
                base.RegisterAvailableViewsCore(collection);
                collection.Add(new MyGridViewInfoRegistrator());
            }
        }

        public class MyGridViewInfoRegistrator : GridInfoRegistrator {
            public override string ViewName { get { return "MyGridView"; } }
            public override BaseView CreateView(GridControl grid) {
                return new MyGridView(grid as GridControl);
            }
        }
        public class MyGridView : GridView {
            public MyGridView(GridControl ownerGrid) : base(ownerGrid) { }
            public MyGridView() { }


            protected virtual bool RowEqual(int focusedRowHandle, int newRowHandle) {
                if(IsDesignMode)
                    return focusedRowHandle == newRowHandle;
                DataRow row1 = GetDataRow(focusedRowHandle);
                DataRow row2 = GetDataRow(newRowHandle);
                return row1 == row2;
            }

            protected override void DoChangeFocusedRowInternal(int newRowHandle, bool updateCurrentRow) {
                if(this.lockFocusedRowChange != 0) return;
                if(!IsValidRowHandle(newRowHandle))
                    newRowHandle = DevExpress.Data.DataController.InvalidRow;
                if(RowEqual(FocusedRowHandle, newRowHandle))
                    return;
                int currentRowHandle = FocusedRowHandle;
                BeginLockFocusedRowChange();
                try {
                    DoChangeFocusedRow(FocusedRowHandle, newRowHandle, updateCurrentRow);
                }
                finally {
                    EndLockFocusedRowChange();
                }
                RaiseFocusedRowChanged(currentRowHandle, newRowHandle);
            }
        }
    }
...