2010-11-17 37 views
0

我正試圖改進Winforms項目,其中數據錶行存儲在ListViewItems的Tag屬性中。當數據表被重構爲List <T>(或者實際上包含列表的類)時,如果我可以通過使用ListView的子類來使Tag屬性具有通用性,它將非常有幫助。通用WinForms ListView(與標籤有關)

在最好的世界中,我希望標籤屬性被替換爲公共標籤{get;設置;}包裝base.Tag並施放它。 第二好的應該是Obsoleting Tag並提供像TypedTag一樣的新屬性,像上面一樣工作。

我認爲這將涉及至少ListView,ListViewItemCollection,SelectedListViewItemCollection和ListViewItem的子類化或組合聚合,我不知道如何去做。

簡而言之:

ListView<Employee> lvwEmployees; 

應該導致本是可能的:

Employee selected = lvwEmployees.SelectedItems[0].TypedTag; 

,並給予這樣的編譯錯誤:

DataRow selected = lvwEmployees.SelectedItems[0].TypedTag; 

這可能嗎?它已經完成了嗎? 項目是dotnet 2.0,但我想我會嘗試升級它,如果它有幫助的話。

編輯:事實證明,所有者構造函數的參數都是一個特定的集合需要掛鉤到內部集合。因此,以下工作:

ListView a = new ListView(); 
a.Items.Add("Hello"); 
Assert.AreEqual(1, new ListView.ListViewItemCollection(a).Count); 

這使得它很容易創建一個通用的標記ListView。我稍後會發佈一個完整的解決方案。 :)

EDIT2:這裏的解決方案: http://thecarlr.blogspot.com/2010/11/generic-listview.html

EDIT3:對於設計師的支持,只需添加一個非通用的子類,並使用它。 示例:如果您打算在表單中使用ListView <Employee>,請在另一個文件中創建ListViewEmployee:ListView <Employee>,並在表單中使用ListViewEmployee。

添加其中一個listviews的最簡單方法是將正常的listview添加到窗體,然後在源文件中更改它的類型。 (如果你不知道它在哪裏聲明或實例化,請改爲查找或使用正常的listview。)

+0

有一個類似的話題討論http://stackoverflow.com/questions/1126404/is-there-an-easy-way-to-associate-an-event-with-a-listviewitem – stuartd 2010-11-17 17:32:27

回答

0

這裏的解決方案: http://thecarlr.blogspot.com/2010/11/generic-listview.html

享受:)

/卡爾

+0

此解決方案的主要問題是通用ListView <>不能在Designer中使用。所以除非你打算手寫所有的UI代碼(或者編輯Designer.cs),否則這個解決方案並不是很有用。 – Grammarian 2010-11-18 13:15:43

+0

啊,感謝您注意並讓我知道!我必須考慮這一點。 :) – 2010-11-18 14:54:05

+0

這似乎是設計師問題真的不是問題。我需要做的就是再次繼承到一個非泛型類,並使用它。 – 2010-11-19 07:28:32

1

你犯了錯誤的類通用。 SelectedItems [0]是一個ListViewItem,而不是一個ListView。

沒有任何事情可以改變Items和SelectedItems屬性的類型。您當然可以從ListViewItem派生自己的類,並添加您想要存儲的屬性。不需要另一個Tag屬性。添加它們時不會遇到任何問題,但是當您從Selected/Items集合中檢索它們時,需要將它們轉換回派生類。

通常,通過僅將ListView作爲模型的視圖來避免這種類型的代碼。 ListViewItem.Index應始終適合從模型中獲取類型安全引用。

+0

我想使整個類的鏈,而不僅僅是ListViewItem。 製作結構沒有問題,但是構建和分配ListViewItem的項目是私有的(或未實現的)更成問題。 – 2010-11-17 19:16:21

+0

呃,你可以做任何數量的不同的listview項目類。只要它們來自ListViewItem。否則,你不能將它們添加到ListView的Item集合中。 ListViewItem中有私人成員需要保持Windows快樂。 – 2010-11-17 19:39:19

+0

是的,但ListView的Item集合不是通用的,因此它需要被覆蓋。 – 2010-11-17 19:46:40

0

VS設計師根本無法處理抽象的或通用控件(not for want of asking)。

解決此限制的方法之一是圍繞標準ListView寫一個類型安全包裝。

事情是這樣的:

public class TypedListView<T> where T : class 
{ 
    public TypedObjectListView(ListView lv) { 
     this.lv = lv; 
    } 
    private ListView lv; 

    public virtual T SelectedObject { 
     get { return (T)this.lv.SelectedItems[0].Tag; } 
    } 

    // Lots more methods/properties 
} 

您在Designer中創建一個正常的ListView,然後當你想訪問它,您可以創建和使用您的適配器來代替。就像這樣:

var typedListView = new TypedListView<Employee>(this.listView1); 
Employee selectedEmployee = typedListView.SelectedObject; 

您需要提供您想要使用的每個ListView屬性或方法的類型版本。

ObjectListView項目採取這種方法來創建一個TypedObjectListView這完全是你在問什麼。

+0

哇,ObjectListView看起來非常好。我必須研究那一個。非常感謝! – 2010-11-18 14:46:33

+0

我喜歡適配器的想法btw,但它不是理想的,因爲它很容易通過正常變量,以便有其他類型的「標籤」的行。 – 2010-11-18 14:52:12