2011-05-05 153 views
3

這個問題困擾了我幾年,也許這裏有人知道一個簡單的解決方案,因爲我只是再次遇到它。更改數據源時DevExpress XtraGrid FocusedRowChanged事件問題

問:是否有任何方法讓XtraGrid在新的(不同的)數據源被分配給網格之前「忘記」當前關注的行索引?

背景 我們使用XtraGrid作爲一種控制器,用於在多窗格Winform的另一個面板中顯示的內容。

現在想象一下假設場景,XtraGrid的數據源根據菜單選擇不斷變化。菜單項1使用自助餐廳中今天的主菜單列表填充網格:Id,Name。菜單項2使用用戶當天必須致電的客戶列表填充網格:ID,名稱。重要的是,這些是獨立的不同數據源,並且網格的數據源正在分配和重新分配。

對於這個問題關鍵事實: 我們希望網格的FocusedRowChanged事件是單一的地方我們陷阱用戶的控制器電網選擇。我們是「沒有意大利麪代碼」的商店。 FocusedRowChanged比單擊事件更好,因爲它也處理鍵盤導航。具有焦點的行包含我們需要從數據庫中獲取以在面板#2中顯示的詳細記錄的ID。這項工作 - 大部分時間是

下面是它不工作的方式:假設在給定的一天,用戶必須聯繫的客戶列表只包含一行。所以網格中的第一個(也是唯一)行就是關注的行。現在我們假設用戶進入菜單並選擇菜單項來顯示當天的食堂主菜。當用戶點擊Entrees列表中的第一個項目時,FocusedRowChanged事件不會觸發,因爲網格保留了來自先前數據源的關注行索引的內存。重點行索引尚未更改。因此用戶的選擇不會觸發任何事情。

我試圖讓DevExpress提供第二個面向行對象的模式(與面向行索引的方法不同),網格中的每一行都有一個GUID,而FocusedRowChanged事件會在不管關注的行索引是否相同,當前關注的行的GUID都不同於先前關注的行的GUID。這將允許動態更改數據源並啓用所需的行爲。但他們反對。

因此,我會再次問我的問題,是否有任何方法讓XtraGrid在新數據源分配給網格之前「忘記」當前關注的行索引?

回答

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

UPDATE

我的代碼:

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

當我按照知識庫文章中的說明進行操作時,我可以在調試器中輸入DoChangeFocusedRowInternal事件(參見上文)並逐步完成代碼。但我的網格從未被視覺渲染。我錯過了什麼? – Tim 2011-05-11 16:53:35

+0

當我嘗試從工具箱中刪除MyGrid(按照KB繼承)到表單上時,VS2010崩潰。我希望DevExpress可以直接調用這個小優化(FocusedRowHandle == newRowHandle)return;),除非它使用某些設計時屬性關閉,開發人員可以根據原始問題更改數據源。 – Tim 2011-05-11 17:15:49

+0

我不知道你使用的代碼,所以我不能評論它。無論如何,我已經用所有必需的課程更新了我的答案。我希望它能幫助你。 – 2011-05-11 19:30:41

3

蒂姆,我只好當電網只有在它的一行數據,然後改變數據源的相同問題。我在設置新的數據源之後通過設置gridview.FocusedRowHandle = -1來解決它。

0

您可以訂閱的DataSourceChanged事件,當數據源改變時會觸發(你猜對了!),那麼你可以得到使用GetFocusedObject()的對象,並顯示爲其他電網相關項目...

+2

是的,但DataSourceChanged導致意大利麪條。重點是能夠在一個地方以一種方式做到這一點。 <>我想問一個簡單的問題:「我在看另一排嗎?」 DevExpress問這個更復雜的問題:「這一行在數組中佔據了不同的位置?」由於底層數據源可以更改,因此使用數組位置作爲相同/差異的指示器不如使用某些INTRINSIC到行對象,如行GUID。 – Tim 2011-11-10 20:55:51

1

在類似的情況,我訂閱了

FocusedRowObjectChanged

事件(使用的DevExpress 16.1)。

+0

我們升級的另一個原因。這將幫助我解決這個問題。謝謝。 – Tim 2017-07-01 16:42:22