Search code examples
c#vb.netinheritanceuser-controlspartial

Shared Base Class for numerous winforms UserControls?


This feels like I'm going to kick myself when I find the answer. I want a number of UserControls to share some properties (like ID) and Events (that is they will all raise the same event). I tried creating a BaseClass UserControl and then tried Inherits BaseClass on my UserControls. However, I get the error:

Base class 'BaseClass' specified for Class Viewer cannot be different from the base class UserControl of one of its other partial types.

What am I missing here?

EDIT: For clarity, a bit of code. This hopefully illustrates how I would like it to work:

Public Class BaseUserControl
    Inherits UserControl

    Public Property ID
    Public Event ItemSelected()

End Class

Public Class Browser
    Inherits BaseUserControl

    Private Sub ButtonPressed() Handles Button1.click

        RaiseEvent ItemSelected()

    End Sub
End Class

Public Class NavBar
    Inherits BaseUserControl

    Private Sub EnterKeyDown() Handles TextBox1.KeyDown

        RaiseEvent ItemSelected()

    End Sub
End Class

Public Class Main

    Dim WithEvents browser As Browser With {.id = 12}
    Dim WithEvents navbar As NavBar With {.id = 624}

    Public Sub New()

        Me.controls.add(browser)
        Me.controls.add(navbar)

    End Sub

    Private Sub SelectionInBrowser() Handles brower.ItemSelected
        'Do amazing stuff
    End Sub

    Private Sub SelectionInNavBar() Handles navbar.ItemSelected
        'Do amazing stuff
    End Sub

End Class

Solution

  • You must create your base class as a UserControl. E.g. name it BaseUserControl. Compile it. Then right click on the project or a folder in the project and click Add > New Item. Then select Windows Forms on the left hand side and then Inherited User Control (Windows Forms). Give it a name and click the Add button. Now a dialog opens where you can select your BaseUserControl. Then click OK. Visual Studio does some magic for you. E.g. it overrides Dispose in the designer generated code. You could do it manually, but like this you get it right for free.

    You can place controls on the BaseUserControl. They will be inherited and visible in the deriving user controls.

    Note that you must change the modifier of the controls in the base user control to Protected, Proteced Friend or Public to enable them to be modified in the inheriting user control.


    Example of inheritance. In BaseUserControl I placed two buttons Button1 and Button2 and made them Protected to make them visible in the derived classs. Then I double clicked on Button1. This creates a Button1_Click event handler. I changed its signature to

    Public Class BaseUserControl
        Protected Overridable Sub Button1_Click(sender As Object, e As EventArgs) _
            Handles Button1.Click
    
            MessageBox.Show($"Hello from {NameOf(BaseUserControl)}.{NameOf(Button1_Click)}")
        End Sub
    End Class
    

    i.e., make it Protected Overridable. This is not strictly necessary, but it allows you to override it in the descendants.

    Saved and compiled and then opened MyUserControl where the two buttons are visible. Clicked on Button2 which does not yet have a clicked event handler to create one.

    Public Class MyUserControl
        Private Sub Button2_Click(sender As Object, e As EventArgs) _
            Handles Button2.Click
    
            MessageBox.Show($"Hello from {NameOf(MyUserControl)}.{NameOf(Button2_Click)}")
        End Sub
    
        Protected Overrides Sub Button1_Click(sender As Object, e As EventArgs)
            MyBase.Button1_Click(sender, e)
            MessageBox.Show($"Hello from {NameOf(MyUserControl)}.{NameOf(Button1_Click)}")
        End Sub
    End Class
    

    As you can see I also did override Button1_Click. MyBase.Button1_Click(sender, e) calls the original implementation from the BaseUserControl.

    Then I placed MyUserControl on a Form and started the application. A click on Button1 first shows:

    Hello from BaseUserControl.Button1_Click

    and after closing the first message box by clicking OK

    Hello from MyUserControl.Button1_Click

    A click on Button2 shows:

    Hello from MyUserControl.Button2_Click