Jimmy
Jimmy

Reputation: 23

Correct way to reference a class's inherited property?

I am positive this is something very simple, but I am having complete brain freeze.

I am trying to create my own control which will add some specific functionality to a textbox, and ultimately want this control to be available in my toolbox for use throughout my project.

As an example, I would like to add this new control to my form, change the .Text property to "Something" and then perform some logic on the .Text property in the New() sub, however me.text is always returning "", meaning my logic fails.

Public Class Class1
    Inherits Windows.Forms.TextBox

    Public Sub New()
        If Me.Text = "Something" Then
            MessageBox.Show("Do something")
        End If
    End Sub
End Class

Any advice on how to overcome this hurdle?

Thanks in advance.


Cont....

Ok, so I think some more context would be good here.

This is something I wanted to try, to ease myself back into OOP, as I thought (!) it would be an easy starting point.

Im sure there is a class that I could download that would do everything I need, but I want to learn, not just copy/pase code from wherever I find.

So, the objective is to have a textbox which will also offer a "Caption" property. This property will contain text that is displayed in the textbox until it is clicked, ie "Your Name", and you click to then enter your name (basic stuff).

The original code posted was trying to demonstrate the issue I was having with obtaining the .Text property value in the New() method, as this is where I was trying to do some comparisons between .text and Caption. The code has now changed, and I no longer do this.

The main issue I am having at the moment is... when I add my control to a windows form, the textbox (.text) is empty, and I want it to be populated with the caption.

The code posted below is where I am after much trial and error. It's not too pretty, and theres some things that need to be thought about in more detail, but ultimately my current issue is getting the .text property populated with what I want and that being shown in the designer.

Public Class TextBoxWithCaption
    Inherits Windows.Forms.TextBox

    Dim Caption_Text As String = "Caption"                               ' Define default caption property value
    Dim Caption_TextForeColor As Color = SystemColors.ControlDarkDark

    Dim NoCaption_TextForeColor As Color = SystemColors.WindowText

    Public Sub New()

        MyBase.New()
        Me.Text = Caption
        Me.Width = 150
        Me.ForeColor = Caption_TextForeColor
    End Sub

    Property Caption() As String
        Get
            Return Caption_Text
        End Get
        Set(value As String)

            ' Caption has been changed.
            '

            If Me.Text = Caption_Text Or String.IsNullOrEmpty(Me.Text) Then
                ' Caption property has changed, textbox has no user defined value, update the textbox with the new caption
                Me.Text = value
            End If

            Caption_Text = value

        End Set

    End Property


    Private Sub TextBoxWithCaption_GotFocus(sender As Object, e As EventArgs) Handles Me.GotFocus

        If Me.Text = Caption Then
            ' If the caption is displayed, then clear it ready for the user to type
            Me.Text = ""
            Me.ForeColor = NoCaption_TextForeColor
        End If
    End Sub


    Private Sub TextBoxWithCaption_LostFocus(sender As Object, e As EventArgs) Handles Me.LostFocus

        If Me.Text = "" Then
            ' If the user has not typed anything, restore the caption
            Me.Text = Caption
            Me.ForeColor = Caption_TextForeColor
        End If
    End Sub

End Class

Upvotes: 0

Views: 318

Answers (2)

T.S.
T.S.

Reputation: 19394

you can still do it and this is correct way because you want call constructor on underlying type

Public Sub New()
    MyBase.New() '<-- this will init yout base text box and now you can use it

    Me.Text = "Something" 

End Sub

But if you had a tool like Resharper, it would warn you about "Virtual member call in constructor", which potentially can produce unexpected results with your property. You can read about online. To solve this issue add this property

Public Overrides NotOverridable Property Text As String
    Get
        Return MyBase.Text
    End Get
    Set (value as string)
        MyBase.Text = value
    End Set
End Property

Upvotes: 1

Visual Vincent
Visual Vincent

Reputation: 18320

The initial value of the Text property will always be an empty string.

When changing a property through the designer the constructor will always be called prior to changing the property. This is because the control must be created before you can modify it. Modifying the Text property of a Class1 variable that has not been initialized will throw a NullReferenceException.

If you look in your form's .Designer.vb file in the InitializeComponent() method, it would look something like this:

Private Sub InitializeComponent()
    Me.components = New System.ComponentModel.Container()
    Me.Class11 = New YourNamespace.Class1()
    Me.SuspendLayout()
    '
    'Class11
    '
    Me.Class11.Text = "Something"

    ...
End Sub

So in short: What you're doing is not possible unless you pass a value immediatelly to the constructor.

Upvotes: 1

Related Questions