更改数据源时DevExpress XtraGrid FocusedRowChanged事件问题

发布于 2024-11-05 05:14:37 字数 963 浏览 1 评论 0原文

这个问题已经困扰我好几年了,也许这里有人知道一个简单的解决方案,因为我刚刚再次遇到它。

问题:在将新的(不同的)数据源分配给网格之前,有什么方法可以让 XtraGrid “忘记”当前聚焦的行索引?

背景 我们使用 XtraGrid 作为一种控制器,用于在多窗格 Winform 的另一个面板中显示内容。

现在想象一个假设的场景,其中 XtraGrid 的数据源根据菜单选择不断变化。菜单项 1 用自助餐厅今天的主菜列表填充网格:ID、名称。菜单项 2 使用用户当天必须致电的客户列表填充网格:ID、姓名。重要的是,这些是单独的不同数据源,并且网格的数据源正在被分配和重新分配。

这个问题的关键事实: 我们希望网格的 FocusedRowChanged 事件成为我们在控制器网格中捕获用户选择的单一位置。我们是一家“无意大利面代码”商店。 FocusedRowChanged 比单击事件更好,因为它也处理键盘导航。具有焦点的行包含我们需要从数据库中获取以在面板 #2 中显示的详细记录的 ID。这在大部分时间都是有效的。

它的工作原理如下:假设在某一天,用户必须联系的客户列表仅包含一行。因此,网格中的第一行(也是唯一一行)是焦点行。现在假设用户进入菜单并选择菜单项来显示当天的自助餐厅主菜。当用户单击 Entrees 列表中的第一项时,不会触发 FocusedRowChanged 事件,因为网格保留了上一个数据源中的焦点行索引的内存。焦点行索引没有改变。因此用户的选择不会触发任何东西。

我试图让 DevExpress 提供第二种更面向行对象的模式(与面向行索引的方法不同),即网格中的每一行都有一个 GUID,并且只要当前的 GUID 存在,就会触发 FocusedRowChanged 事件。无论焦点行索引是否相同,焦点行都与先前焦点行的 GUID 不同。这将允许数据源的动态更改并实现所需的行为。但他们表示反对。

所以我会再次问我的问题,有没有办法让 XtraGrid 在将新数据源分配给网格之前“忘记”当前聚焦的行索引?

This problem has bugged me for several years and maybe someone here knows a simple solution, since I just ran into it again.

QUESTION: Is there any way to get the XtraGrid to "forget" the current focused row index before a new (different) datasource is assigned to the grid?

BACKGROUND
We use the XtraGrid as a kind of controller for what is displayed in another panel of a multipane Winform.

Now imagine a hypothetical scenario where the datasource of the XtraGrid keeps changing according to menu selections. Menu item 1 populates the grid with a list of today's entrees in the cafeteria: Id, Name. Menu item 2 populates the grid with a list of Customers the user must phone that day: ID, Name. Important thing is that these are separate distinct datasources, and the grid's datasource is being assigned and reassigned.

CRITICAL FACT FOR THIS QUESTION:
We want the grid's FocusedRowChanged event to be the single place where we trap the user's selection in the controller grid. We are a "no spaghetti code" shop. FocusedRowChanged is better than a click event because it handles keyboard navigation too. The row with the focus contains the ID of the detail record we need to fetch from the database for display in Panel #2. This works--most of the time.

Here's how it doesn't work: let's say that on a given day, the list of customers the user must contact contains only one row. So the first (and only) row in the grid is the focused row. Now let's say that the user goes up to the menu and selects the menu item to display the day's cafeteria entrees. When the user clicks on the first item in the Entrees list, the FocusedRowChanged event does NOT fire because the grid has retained a memory of the focused row index from the previous datasource. The focused row index has not changed. And thus the user's selection doesn't trigger anything.

I tried to get DevExpress to offer a second more row-object-oriented mode (as distinct from row-index-oriented approach) whereby each row in the grid would have a GUID, and the FocusedRowChanged event would fire whenever the GUID of the currently focused row differed from the GUID of the previously focused row, regardless of whether the focused row index happened to be the same. This would allow dynamic changes of datasource and enable the desired behavior. But they demurred.

So I'll ask my question again, Is there any way to get the XtraGrid to "forget" the current focused row index before a new datasource is assigned to the grid?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

哭了丶谁疼 2024-11-12 05:14:37

蒂姆,当网格中只有一行数据然后更改数据源时,我遇到了完全相同的问题。我通过在设置新数据源后设置 gridview.FocusedRowHandle = -1 来解决它。

Tim, I had the exact same problem when the grid only had one row of data in it and then changed data sources. I solved it by setting the gridview.FocusedRowHandle = -1 after setting the new datasource.

无声情话 2024-11-12 05:14:37

在类似的情况下,我订阅了

FocusedRowObjectChanged

事件(使用 DevExpress 16.1)。

In a similar situation, I am subscribing to the

FocusedRowObjectChanged

event (using DevExpress 16.1).

哎呦我呸! 2024-11-12 05:14:37

我认为解决这个问题的最佳方法是创建一个新的 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);
            }
        }
    }

I think that the best solution to this problem is to create a new GridView object and override its DoChangeFocusedRowInternal method. Below you will find the default implementation of this method. All you need to do is to change the marked row just as your needs dictate. Also, take a look at the How to create a GridView descendant class and register it for design-time use article, it contains some useful information.

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);
        }
    }

UPDATE

My code:

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);
            }
        }
    }
梦在夏天 2024-11-12 05:14:37

您可以订阅 DataSourceChanged 事件,该事件将在数据源更改时触发(您猜对了!),这样您就可以使用 GetFocusedObject() 对象并显示其他网格的相关项目...

You can subscribe on the DataSourceChanged event which will fire when Data source changes (you guessed it!) so then you can get using GetFocusedObject() the object and display the relevant items for the other grid...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文