【问题标题】:UserControl can't shadow Enabled property when created dynamically [duplicate]动态创建时,UserControl 无法隐藏 Enabled 属性[重复]
【发布时间】:2021-05-23 08:04:01
【问题描述】:

我有一个自定义的 UserControl(基本上是一个花哨的 Button),它需要知道何时启用/禁用该控件以更改绘图颜色。

我在控件中添加了一个 Shadows 属性,如下所示:

Private _enabled As Boolean

Public Shadows Property Enabled() As Boolean
    Get
        Return Me._enabled
    End Get
    Set(value As Boolean)
        Me._enabled = value

        ' My code here to change the drawing colors

    End Set
End Property

当使用 GUI 设计器(预编译)创建我的控件时,此方法似乎可以正常工作。但是,当我在运行时动态创建控件时,GetSet 代码永远不会运行。

有什么可能导致这种情况的想法吗?

【问题讨论】:

  • 这完全是错误的做法。您应该做的是覆盖 OnEnabledChanged 方法,这就是引发 EnabledChanged 事件的原因。
  • + 这是一个运行时属性。
  • 您的代码实际上并没有触及基本的Enabled 属性这一事实表明您实际上可能并不希望控件被真正禁用,而只是您自己的被禁用的逻辑版本。这是真的,还是您真的希望 Windows 和 .NET 将您的控件视为已禁用?如果这是您想要的,那么覆盖 OnEnabledChanged 实际上不会做您想做的事情,因为它将与现有的 Enabled 属性一起使用。

标签: vb.net winforms properties


【解决方案1】:

很难确定,因为您没有提供足够的信息,但我怀疑我知道问题所在。当您隐藏一个成员时,您必须通过派生类的引用访问该成员才能调用派生实现。如果您使用基本类型的引用,那么它就是您将调用的基本实现。这与覆盖成员时不同,在这种情况下,无论引用的类型如何,都将调用派生实现。我通常将其总结为覆盖遵循对象的类型,而阴影遵循引用的类型。尝试运行此代码以查看其实际效果:

Module Module1

    Sub Main()
        Dim dc As New DerivedClass

        dc.OverrideMethod()
        dc.ShadowMethod()

        Dim bc As BaseClass = dc

        bc.OverrideMethod()
        bc.ShadowMethod()
    End Sub

End Module

Public Class BaseClass

    Public Overridable Sub OverrideMethod()
        Console.WriteLine("BaseClass.OverrideMethod")
    End Sub

    Public Sub ShadowMethod()
        Console.WriteLine("BaseClass.ShadowMethod")
    End Sub

End Class
Public Class DerivedClass
    Inherits BaseClass

    Public Overrides Sub OverrideMethod()
        Console.WriteLine("DerivedClass.OverrideMethod")
    End Sub

    Public Shadows Sub ShadowMethod()
        Console.WriteLine("DerivedClass.ShadowMethod")
    End Sub

End Class

这是输出:

DerivedClass.OverrideMethod DerivedClass.ShadowMethod DerivedClass.OverrideMethod BaseClass.ShadowMethod

如您所见,通过基类型的引用调用被遮蔽的方法会调用基实现,而通过基类型的引用调用被覆盖的方法会调用派生实现。

在您的特定情况下,当您在运行时添加实例时,您没有控件特定类型的字段可以访问它,因此您可能通过表单的Controls 集合访问它。这将返回一个Control 引用,因此,如果您要通过它访问Enabled 属性,它将是您调用的基本实现。如果要调用派生实现,则需要将该引用转换为控件的实际类型。这样做的一种选择是使用OfType 方法同时按类型过滤和强制转换,例如

Dim firstFancyButton = Controls.OfType(Of FancyButton)().First()

否则,执行显式转换,例如

Dim firstFancyButton = DirectCast(Controls("FancyButton1"), FancyButton)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-07
    • 2014-08-18
    • 2018-08-31
    • 2013-10-17
    • 1970-01-01
    • 2016-12-17
    • 2016-03-28
    相关资源
    最近更新 更多