如何使类属性的行为类似于RadioButton上的Checked属性?

时间:2012-06-01 15:38:23

标签: .net vb.net

我有一个非常简单的类,它包含一些公共属性--ID,Text,Color等,以及一个名为'SelectedItem'的布尔值。就像RadioButtons上的Checked属性一样,只有一个项目可以将SelectedItem属性设置为特定组中的True。注意:将有几个单独的组(列表),每个组只允许一个项目SelectedItem = True

我的第一个想法是,我可能只需要处理课外的所有内容,当选择另一个项目时,为特定列表中的每个其他项目设置SelectedItemFalse。但这对我来说似乎相当不优雅。所以我一直在想着如何在这个类中完成它。例如:我可能有一个名为“GroupName”的私有字符串属性 - 在添加类的新实例时在New子集中设置 - 然后使用私有共享方法设置每个项目的{{1}属性为SelectedItem提供该项目与新选择的项目具有相同的False?我会这样做,但我不知道如何枚举该类中的每个实例,或者是否可能。是吗?或者是否有另一种(更好的)方法来实现我的目标?


修改

感谢所有的建议和意见,我们非常感谢。

在Tim和Cyborgx37的评论背后,我决定遵循他们的建议并使用CollectionBase作为项目经理类。这是我到目前为止的简化版本:

GroupName

可以看出:我没有实例化一个新的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过程,而是简单地传递新项目的详细信息并且过程正在创建这些项目。我不知道这是好还是坏 - 请告知 - 但我已经完成了,因为我无法弄清楚如何使SelectedItem属性只能由经理写,所以我想避免直接访问可以将Add属性设置为SelectedItem的对象,而不取消选择同一组中的所有其他项目。当然,这仍然有可能将变量设置为管理者列表项之一并从那里设置,所以我仍然想知道如果可能的话我怎么能阻止它。


更新
我最后没有使用上面的代码,而是选择使用Cyborgx37的解决方案 - 尽管有关于最佳实践的警告,这似乎对我来说非常好。我还意识到我需要在另一个可以选择多个 项的情况下使用相同的类,因此很容易向管理器添加一个布尔属性来启用它。

2 个答案:

答案 0 :(得分: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无效。

答案 1 :(得分: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));


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