这个问题困扰了我好几年了,也许这里的某个人知道一个简单的解决方案,因为我刚刚遇到它。
问题:在将新的(不同的)数据源分配给网格之前,有没有办法让XtraGrid“忘记”当前的聚焦行索引?
背景 我们使用XtraGrid作为一种控制器,用于在多窗格Winform的另一个面板中显示的内容。
现在假设一个假设的场景,XtraGrid的数据源会根据菜单选择不断变化。菜单项1使用自助餐厅中今天主菜的列表填充网格:Id,Name。菜单项2使用用户必须在当天打电话的客户列表填充网格:ID,名称。重要的是,这些是独立的不同数据源,并且正在分配和重新分配网格的数据源。
这个问题的关键事实: 我们希望网格的FocusedRowChanged事件是单个地方,我们在控制器网格中捕获用户的选择。我们是一个“没有意大利面条代码”的商店。 FocusedRowChanged比点击事件更好,因为它也处理键盘导航。具有焦点的行包含我们需要从数据库中获取以在Panel#2中显示的详细记录的ID。这很有用 - 大部分时间。
以下是它不起作用的方式:让我们说在给定的一天,用户必须联系的客户列表只包含一行。因此,网格中的第一行(也是唯一一行)是聚焦行。现在让我们说用户进入菜单并选择菜单项以显示当天的自助餐厅主菜。当用户单击“主体”列表中的第一个项目时,FocusedRowChanged事件不会触发,因为网格保留了来自先前数据源的焦点行索引的内存。焦点行索引没有改变。因此,用户的选择不会触发任何内容。
我试图让DevExpress提供另外一种面向行对象的模式(与面向行索引的方法不同),网格中的每一行都有一个GUID,每当GUID都会触发FocusedRowChanged事件无论聚焦行索引是否恰好相同,当前聚焦行的行与先前聚焦行的GUID不同。这将允许动态更改数据源并启用所需的行为。但他们反对。
所以我再次问我的问题,在将新的数据源分配给网格之前,有没有办法让XtraGrid“忘记”当前的聚焦行索引?
答案 0 :(得分:3)
答案 1 :(得分:1)
在类似的情况下,我订阅了
FocusedRowObjectChanged
事件(使用DevExpress 16.1)。
答案 2 :(得分:0)
我认为解决此问题的最佳方法是创建一个新的GridView对象并覆盖其DoChangeFocusedRowInternal方法。您将在下面找到此方法的默认实现。您需要做的就是根据需要更改标记的行。另外,请查看How to create a GridView descendant class and register it for design-time use文章,其中包含一些有用的信息。
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);
}
}
}
答案 3 :(得分:0)
您可以订阅DataSourceChanged事件,该事件将在数据源更改时触发(您猜对了!),这样您就可以使用GetFocusedObject()对象并显示其他网格的相关项...