2012-06-01 33 views
1

我有一個非常簡單的類,它擁有一些公共屬性 - ID,文本,顏色等,以及一個名爲'SelectedItem'的布爾值。就像RadioButton上的Checked屬性一樣,只有一個項目的SelectedItem屬性可以在特定組內設置爲True。注意:將會有幾個單獨的組(列表),每個組只允許一個項目與SelectedItem = True我如何使一個類屬性行爲像一個RadioButton上的Checked屬性?

我的第一個想法是,我可能只需要處理課外的所有事情,當選擇另一個項目時,將SelectedItem設置爲False爲特定列表中的每個其他項目。但對我來說這似乎相當不雅。所以我一直在想如何在範圍內完成這個課程。例如:我可能有一個名爲say「GroupName」的私有字符串屬性 - 在添加類的新實例時設置在New的子集中 - 然後使用私有共享方法將每個項目的SelectedItem屬性設置爲False,,提供該項目與新選擇的項目具有相同的GroupName?我會這樣做,但我不知道如何從該類中枚舉每個類的實例,或者這是否可能。是嗎?還是有另一種更好的方式來實現我的目標?


編輯

感謝所有的建議和意見,他們都非常讚賞。

在Tim和Cyborgx37評論的背面,我決定遵循他們的建議,並使用CollectionBase作爲項目管理器類。下面是我到目前爲止已經有一個簡化版本:

Public Class ResourceItem 
    Public ID As Integer 
    Public Text As String 
    Public SelectedItem As Boolean 
End Class 

Public Class ResourceItemsManager 
    Inherits System.Collections.CollectionBase 

    Public Sub Add(ByVal iID As Integer, ByVal sText As String) 
     Dim newResItem As New ResourceItem 
     With newResItem 
      .ID = iID 
      .Text = sText 
     End With 
     List.Add(newResItem) 
    End Sub 

    Default Public ReadOnly Property Item(ByVal Index As Integer) As ResourceItem 
     Get 
      If Index < Count And Index >= 0 Then 
       Return CType(List.Item(Index), ResourceItem) 
      Else 
       Return Nothing 
      End If 
     End Get 
    End Property 

    Public Sub ClearAll() 
     List.Clear() 
    End Sub 

    Public Sub SelectItem(ByVal Index As Integer) 
     If Index < Count And Index >= 0 Then 
      For i As Integer = 0 To List.Count - 1 
       List.Item(i).SelectedItem = i = Index 
      Next 
     Else 
      'Exception code here 
     End If 
    End Sub 
End Class 

可以看出:不是實例化一個新的ResourceItem,並將其作爲參數傳遞給經理的Add過程中,我簡單地傳遞新項目的詳細信息,並從中創建項目。我不知道這是一個好還是壞的想法 - 請指教 - 但我已經這樣做了,因爲我無法弄清楚如何讓SelectedItem屬性只能由管理員寫入,所以我想避免直接訪問可以將其SelectedItem屬性設置爲True而不取消選擇同一組中的所有其他項的對象。當然,仍然有可能將一個變量設置爲經理的列表項目之一,並從那裏設置它,所以我仍然想知道如果可能,我可以如何防止這種情況。


UPDATE
我沒有到底使用上面的代碼,而是決定去與Cyborgx37的解決方案 - 這似乎是儘管對最佳實踐的警告非常清楚對我的工作。我也意識到我需要在另一種情況下使用同一個班級,其中可能可能被選中,所以很容易向管理員添加一個布爾屬性來啓用它。

+2

您可以爲您的自定義類型的集合類繼承['CollectionBase'(http://msdn.microsoft.com/en-us/library/system.collections.collectionbase.aspx)。然後您可以確保只檢查一個相同的組。 –

+3

枚舉你需要某種容器類來了解它們。有幾種方法可以做到這一點,但是在某種程度上,他們都會認真對待(東西),這就是你需要決定的東西的參考。 –

+0

@TimSchmelter在.NET中我仍然有點綠,所以它花了很多時間我有點頭腦發熱。我已經通過這個MS演練:[創建你自己的收藏類](http://msdn.microsoft.com/en-us/library/xth2y6ft%28v=vs.71%29.aspx),我想我'做你的建議 - 它似乎工作無論如何。我已經爲集合類添加了一個名爲'SelectItem'的方法,並且我正在使用它枚舉組中的每個項目並適當地設置它們的檢查狀態。這是你想到的嗎?如果是這樣,有沒有辦法讓SelectedItem屬性只讀集合類除外? – Antagony

回答

1

這是一個非常簡單的解決方案。它並不遵循每一個最佳實踐(例如,在ItemManager中公開Items集合可能是一個糟糕的主意),但它展示了與管理器接口的單個​​項目中的中央管理器和屬性。

Module Module1 

Sub Main() 

    Dim l_itemManager As New ItemsManager() 

    Dim l_item1 As New Item(l_itemManager) With {.Description = "Item 1"} 
    Dim l_item2 As New Item(l_itemManager) With {.Description = "Item 2"} 
    Dim l_item3 As New Item(l_itemManager) With {.Description = "Item 3"} 
    Dim l_item4 As New Item(l_itemManager) With {.Description = "Item 4"} 

    l_itemManager.SelectedItem = l_item1 

    Console.WriteLine("Item 1 = " & If(l_item1.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 2 = " & If(l_item2.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 3 = " & If(l_item3.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 4 = " & If(l_item4.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("") 

    l_itemManager.SelectedItem = l_item2 

    Console.WriteLine("Item 1 = " & If(l_item1.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 2 = " & If(l_item2.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 3 = " & If(l_item3.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 4 = " & If(l_item4.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("") 

    l_item3.IsSelected = True 

    Console.WriteLine("Item 1 = " & If(l_item1.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 2 = " & If(l_item2.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 3 = " & If(l_item3.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("Item 4 = " & If(l_item4.IsSelected, "Selected", "Unselected")) 
    Console.WriteLine("") 

    Console.WriteLine("Press any key...") 
    Console.ReadKey(True) 

End Sub 

Class ItemsManager 

    Public Event SelectedItemChanged As EventHandler 

    Public Items As New List(Of Item) 

    Private _item As Item 
    Public Property SelectedItem() As Item 
     Get 
      Return _item 
     End Get 
     Set(ByVal value As Item) 
      _item = value 
      RaiseEvent SelectedItemChanged(sender:=Me, e:=EventArgs.Empty) 
     End Set 
    End Property 

End Class 

Class Item 

    Public Event IsSelectedChanged As EventHandler 

    Private WithEvents _manager As ItemsManager 
    Public ReadOnly Property Manager() As ItemsManager 
     Get 
      Return _manager 
     End Get 
    End Property 

    Private _description As String 
    Public Property Description() As String 
     Get 
      Return _description 
     End Get 
     Set(ByVal value As String) 
      _description = value 
     End Set 
    End Property 

    Public Property IsSelected() As Boolean 
     Get 
      Return Me.Manager.SelectedItem Is Me 
     End Get 
     Set(ByVal value As Boolean) 
      If value Then 
       Me.Manager.SelectedItem = Me 
      Else 
       Me.Manager.SelectedItem = Nothing 
      End If 
     End Set 
    End Property 

    Public Sub New(ByVal manager As ItemsManager) 
     _manager = manager 
     Me.Manager.Items.Add(Me) 
    End Sub 

    Private Sub _manager_SelectedItemChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _manager.SelectedItemChanged 
     RaiseEvent IsSelectedChanged(sender:=Me, e:=EventArgs.Empty) 
    End Sub 

End Class 

End Module 

編輯:

雖然不完全內嵌的最佳實踐,這樣的代碼將工作。最佳實踐高度依賴於上下文,因此如果不知道應用程序的具體細節,很難說「正確」的方法是什麼。也就是說,管理人員和兒童班級(兒童班級打電話進入管理人員以獲得他們的州)的一般概念幾乎適用於所有情況。

我同意@TimSchmelter,CollectionBase會給你最強大的力量。但你可能不需要那麼多的權力來達到你的目的。而且你最終還是不得不使用類似於我發佈的代碼 - 孩子們會向父母詢問他們的地位。

注意:我更正了上面代碼中的一個小錯誤。將選定的項目設置爲未選中將導致沒有任何事情發生。我已經改變了這種行爲,使SelectedItem Nothing。

+0

那麼,這當然有效,但你讓我對你的評論感到緊張,它不是最佳實踐。正如我剛纔提到Tim在回覆他的OP評論時所說的那樣:我仍然對.NET有點綠色,所以如果我能避免它,我真的不想使用壞的方法。 – Antagony

+0

我看到它的問題 - 與這個和蒂姆的建議 - 是我不明白它是如何給我一個很大的優勢,而不是簡單地創建一個程序來取消選擇給定列表中的每個項目並將列表作爲參數傳遞。我可能期望太多,但我更希望有一個更獨立的解決方案 - 即我寧願設置任何項目的SelectedItem屬性,並讓它自動取消選擇其他項目,而不是必須使用一個容器/管理員類。 – Antagony

+1

@Antagony:通過使用從CollectionBase繼承的自定義類,您可以完全控制您的項目。好處是可重用性,最重要的是[封裝](http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29)。當然,你必須自己實現這個功能,但這是正確的。 –

1

將集合傳遞給ctor中的類並在那裏迭代列表。

List<People> peoples = new List<people>(); 
    peoples.add(new People("Group1", peoples)); 
    peoples.add(new People("Group1", peoples)); 
    peoples.add(new People("Group1", peoples)); 


    Pubic Class People, iNotifyPropertyChanged 
    { 
     private List<People> peoples; 
     private bool isChecked = false; 

     public book IsChecked 
     { 
      get { return isChecked; } 
      set 
      { 
       if(isChecked = value) return; 
       isChecked = value; 
       if (isChecked) 
       { 
        foreach (person p in peoples) 
        { 
         if (p.Ischecked && p != this) p.Uncheck(); 
        } 
       } 
      } 
     } 
     public void Uncheck 
     { 
      isChecked = false; 
      NotifyPropertyChanged("IsChecked"); 
     } 

     public People(string group, List<People> _peoples { peoples = _peoples; }; 
    } 
+0

我相信Antagony正在尋找POCO,而不是控制權。 – JDB

+0

@ Cyborgx37請參閱Or。你有沒有投票給我? – Paparazzi

+0

我沒有投票給你。 – JDB

相關問題