【问题标题】:How do I 'follow' a property changing event up the inheritance ladder我如何在继承阶梯上“跟踪”属性更改事件
【发布时间】:2013-12-31 11:55:18
【问题描述】:

我有一个用户控件,它将构成我打算在其上构建的其他复合用户控件的基础。在该基本控件中,我在下面定义了一个属性,其中包含与之相关的 on change 事件。

Private _themeToUse As String
Public Property ThemeToUse As String
    Get
        Return _themeToUse
    End Get
    Set(ByVal value As String)
        _themeToUse = value
        RaiseEvent ThemeToUseOnChange(Me, EventArgs.Empty)
    End Set
End Property

Public Event ThemeToUseOnChange(ByVal sender As Object, ByVal e As EventArgs)


Private Sub ThemeChanging(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ThemeToUseOnChange
    ThemeController.Theme = ThemeToUse
End Sub

我想弄清楚的是我的新用户控件如何使用这个基本控件作为他们自己继承的控件可以利用 on change 事件。

在智能感知建议使用“阴影”后,我尝试将以下内容添加到继承基本控件的新控件中,但它似乎没有被触发。

Shadows Event ThemeToUseOnChange(ByVal sender As Object, ByVal e As EventArgs)


Private Sub ThemeChanging(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ThemeToUseOnChange
    C1ThemeController1.Theme = ThemeToUse
End Sub

谁能告诉我应该如何正确地做这种事情?

谢谢

【问题讨论】:

    标签: vb.net winforms inheritance user-controls


    【解决方案1】:

    将此视为您的基类:

    Public Class First
    
        Public Event ThemeToUseChanged As EventHandler
        Public Event ThemeToUseChanging As EventHandler
    
        Public Property ThemeToUse() As String
            Get
                Return Me.m_themeToUse
            End Get
            Set(ByVal value As String)
                If (value <> Me.m_themeToUse) Then
                    Me.OnThemeToUseChanging(EventArgs.Empty)
                    Me.m_themeToUse = value
                    Me.OnThemeToUseChanged(EventArgs.Empty)
                End If
            End Set
        End Property
    
        Protected Overridable Sub OnThemeToUseChanged(ByVal e As EventArgs)
            If (Not Me.ThemeToUseChangedEvent Is Nothing) Then
                Me.ThemeToUseChangedEvent.Invoke(Me, e)
            End If
        End Sub
    
        Protected Overridable Sub OnThemeToUseChanging(ByVal e As EventArgs)
            If (Not Me.ThemeToUseChangingEvent Is Nothing) Then
                Me.ThemeToUseChangingEvent.Invoke(Me, e)
            End If
        End Sub
    
        Private m_themeToUse As String
    
    End Class
    

    而且这个类继承了First类的一切:

    Public Class Second
        Inherits First
    
    End Class
    

    现在您可以为每个对象的ThemeToUseChanged 事件和ThemeToUseChanging 事件添加句柄:

    Public Class Form1
    
        Public Sub New()
            Me.InitializeComponent()
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            'Test:
            Me._first.ThemeToUse = New Guid().ToString()
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            'Test:
            Me._second.ThemeToUse = New Guid().ToString()
        End Sub
    
        Private Sub ThemeToUseChanged(sender As Object, e As EventArgs) Handles _first.ThemeToUseChanged, _second.ThemeToUseChanged
            If (sender Is Me._first) Then
                'ThemeToUseChanged changed of type `First`
            ElseIf (sender Is Me._second) Then
                'ThemeToUseChanged changed of type `Second`
            End If
        End Sub
    
        Private Sub ThemeToUseChanging(sender As Object, e As EventArgs) Handles _first.ThemeToUseChanging, _second.ThemeToUseChanging
            If (sender Is Me._first) Then
                'ThemeToUseChanging changed of type `First`
            ElseIf (sender Is Me._second) Then
                'ThemeToUseChanging changed of type `Second`
            End If
        End Sub
    
        Private WithEvents _first As New First
        Private WithEvents _second As New Second
    
    End Class
    

    如果你认为Third 类继承Second

    Public Class Third
        Inherits Second
    
    End Class
    

    这是你可以循环继承链的方式:

    Dim obj As First = New Third()
    Dim t As Type = obj.GetType()
    
    Do
        MsgBox(t.FullName)
        t = t.BaseType
    Loop Until (t.BaseType Is Nothing)
    

    【讨论】:

    • 谢谢 Bjorn,这是一个非常好的和优雅的解决方案。
    • @DomSinclair 我很高兴它有帮助!仅供参考:我添加了更多信息。
    【解决方案2】:

    您似乎应该将属性 value 作为事件的一部分,就像鼠标单击事件包括单击和鼠标信息一样:

    Class ThemeChangedEventArgs
        Inherits EventArgs
    
        Public Proptery OldTheme As String
        Public Proptery NewTheme As String
    
        Sub New(oldT As String, newT AS String)
            OldTheme = oldT
            NewTheme = newT
        End Sub
     End CLass
    
     Public Event ThemeChanged(Sender as Object, e As ThemeChangedEventArgs)
    

    然后:

    Property Theme As String
     ...
     Set(value as string)
    
        RaiseEvent ThemeChanged(Me, New ThemeChangedEventArgs(_Theme, value))
        _Theme = Value
     End Set
    

    该事件通常用于通知订阅者 - 就像表单一样 - 主题发生了变化。它们也可用于从子类中冒泡信息,但这或多或少需要父类定义事件并首先了解属性。在这种情况下:

     Property Theme As String
     ...
     Set(value as string)
        MyBase.Theme = value
    
     End Set
    

    这会用更少的代码告诉父类同样的事情,假设属性是在上游而不是在这个类中定义的。

    使用事件进行属性更改的孩子更像这样:

    Class Parent
       ...
       Protected Friend MustOverride Property Theme() As String
    
       Public Event ThemeChanged ...
    

    任何继承自 Parent 的类都需要定义 Theme,所以它知道,只是不知道细节。订阅者事件也在父级别定义,允许事件由实际实现它的任何类触发。

    事件在这些方面派上用场的是内部流程。内心深处发生了一些事情,所以一个类引发了FooChange event,父级在OnFooChange 中响应,执行诸如计算更改的影响之类的操作,然后可能引发诸如FooBarChange 之类的用户事件(对于表单)。 Child 知道 Foo,但 Parent 处理 Bar,因此您可以使用内部事件通知 Parent。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-05
      • 1970-01-01
      • 2016-05-22
      • 2014-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      相关资源
      最近更新 更多