Access a base class property in inheritance class - vb.net

I'm using the base class Button in VB.net (VS2017) to create a new class called CDeviceButton. The CDeviceButton then forms as a base for other classes such as CMotorButton, CValveButton.
I want to set the Tag property in the child class CMotorButton but access it in the constructor in CDeviceButton. Doesn't work for me. It turns up being empty.
The Tag is set in the standard property when inserting the CMotorButtom instance into a form.
I've also tried to ensure teh the parent classes' constructors are run by setting mybase.New() as the first action in each constructor but that didn't change anything.
Any ideas for improvements?
Public Class CDeviceButton
Inherits Button
Public MMIControl As String = "MMIC"
Public Sub New()
MMIControl = "MMIC" & Tag
End Sub
End class
Public Class CMotorButton
Inherits CDeviceButton
Sub New()
'Do Something
end Sub
End Class

When you try to concatenate Tag with a string, you are trying to add an object that is probably nothing. I set the Tag property first and used .ToString and it seems to work.
Public Class MyButton
Inherits Button
Public Property MyCustomTag As String
Public Sub New()
'Using an existing Property of Button
Tag = "My Message"
'Using a property you have added to the class
MyCustomTag = "Message from MyCustomTag property : " & Tag.ToString
End Sub
End Class
Public Class MyInheritedButton
Inherits MyButton
Public Sub New()
If CStr(Tag) = "My Message" Then
Debug.Print("Accessed Tag property from MyInheritedButton")
Debug.Print(MyCustomTag)
End If
End Sub
End Class
And then in the Form
Private Sub Test()
Dim aButton As New MyInheritedButton
MessageBox.Show(aButton.Tag.ToString)
MessageBox.Show(aButton.MyCustomTag)
End Sub

Below is my solution I came up with that works. Basically I make sure that all initialization has taken place before reading the Tag property. What I experienced is that the Tag property is empty until the New() in CMotorButton has completed, even though the Tag property has been set when creating the instance of CMotorButton in the Form. TimerInitate has a Tick Time of 500 ms.
Not the most professional solution but works for what I need at the moment.
Another option could be multi threading but that I haven't tried and leave that for future tryouts.
Public Class CDeviceButton
Inherits Button
Public MMIControl As String = "MMIC"
Public Sub New()
TimerInitiate = New Timer(Me)
End Sub
Private Sub TimerInitiate_Tick(sender As Object, e As EventArgs) Handles TimerInitiate.Tick
If Tag <> Nothing Then
TimerInitiate.Stop()
MMIControl = "MMIC" & Tag
End If
End Sub
End class
Public Class CMotorButton
Inherits CDeviceButton
Sub New()
'Do Some stuff
TimerInitiate.Start()
End Sub
Private Sub CMotorButton_Click(sender As Object, e As EventArgs) Handles Me.Click
End Class

Related

Modify the components of the main class through another class

We have a school project and I'm trying to break our code into groups. I set my FormBorderStyle to None so I can modify it. But can I use another class to modify the components I have in my main?
An example would be:
Public Class main
Private Sub btn_title_bar_exit_Click(sender As Object, e As EventArgs) Handles btn_title_bar_exit.Click
Me.Close()
End Sub
Private Sub btn_title_bar_minimize_Click(sender As Object, e As EventArgs) Handles btn_title_bar_minimize.Click
Me.WindowState = FormWindowState.Minimized
End Sub
End Class
Public Class user_interface
'Modify components and the form through here
'example: btn_exit.ForeColor = Color.Black
'example: Me.Close()
End Class
Also wondering, this a good way to break code?
If you just want to separate routines (functions/methods/variables declarations...) because you have loads of code filling your class file, just use :
1) the Partial keyword
Public Partial Class MainClass
' MAIN CONTENT
Public Sub New()
Me.InitializeComponents()
' ...
End Sub
' ...
End Class
and in another file :
Public Partial Class MainClass
' USER INTERFACE HANDLERS...
'Modify components and the form through here
'example: btn_exit.ForeColor = Color.Black
'example: Me.Close()
' ...
End Class
So this is the same Class, and other classes may NOT be able to access/modify its members.
2) or either use #Region to split your code and group them :
Public Class MainClass
#Region "Instanciation..."
Public Sub New()
Me.InitializeComponents()
' ...
End Sub
#End Region
#Region "User Interface..."
'Modify components and the form through here
'example: btn_exit.ForeColor = Color.Black
'example: Me.Close()
Public Sub btn1_Click(...)
Public Sub Picture1_MouseMove(...)
#End Region
#Region "Public Properties..."
'...
#End Region
End Class
Then use the plus/minus to unfold/fold that part of the code.
If you really want to edit the members of your MainClass from another class, say, RemoteClass, there are TONs of way doing it, and it depends on what exactly you want to do.
You could make everything Public in your MainClass :
Locate your Form designer file (the one containing the declaration of all the controls of your Form) and change each declaration to Public.
Private pictureBox1 As Picturebox
' becomes
Public pictureBox1 As Picturebox
(Or just click on a control in the IDE, and change its accessibility level to Public)
Then if you can pass a variable pointing to an instance of MainClass in an instance of RemoteClass, then, through RemoteClass, you can access TheMainClassInstance.pictureBox1, and change its size, location, etc. everything.
Then how to create an instance of MainClass in RemoteClass ? It depends on the structure of your application... Without details, guess what.. we'll have to guess..!
Public Class RemoteClass
Private _InstanceOfMainClass As MainClass = Nothing
Public Sub New(ByRef NewInstanceOfMainClass As MainClass)
_InstanceOfMainClass = NewInstanceOfMainClass
' ^^ this is one way doing it.
' ...
End Sub
' ...
Private Sub ChangeBackgroundColor()
_InstanceOfMainClass.picturebox1.BackColor = Color.Black ' and voila !
End Sub
End Class
Then you have a MainClass in your RemoteClass. Don't forget to dispose of _InstanceOfMainClass to avoid Memory Leak (I assume you know how to..)
How many instances of MainClass do you have ?
If it's just one, and you have several RemoteClass classes, then you could consider to make the member of MainClass you want to access as static (shared) members.
Public Class MainClass
Private Shared _MyInstance As MainClass = Nothing
Private Shared Sub InitializeMyInstance()
If _MyInstance Is Nothing Then
_MyInstance = New MainClass(...)
Else
If _MyInstance.IsDisposed Then
' Requires an IDisposable interface
' and handling of Me.Closed event elsewhere...
_MyInstance = Nothing
_MyInstance = New MainClass(...)
End If
End If
End Sub
Public Shared ReadOnly Property MyInstance() As MainClass
Get
InitializeMyInstance()
Return _MyInstance
End Get
End Property
Public Shared ReadOnly Property PictureBox1() As PictureBox
Get
Return MyInstance.pictureBox1
End Get
End Property
' Create as many Properties as required...
End Class
Then in ANY RemoteClass instance, you just call :
MainClass.PictureBox1.Width = 400
MainClass.Close()
MainClass.PictureBox1.Height = 200
But as I said, this works only if you only have a single instance of MainClass.
If you have several MainClass instances and several RemoteClass instances, consider using Unique IDs and a static function/property to access a specific instance.
How to create an ID ?
Public Class MainClass
Private Shared _NextID As Integer = 0
Private _ID As Integer
Public ReadOnly Property ID() As Integer
Get
Return _ID
End Get
End Property
Public Sub New(...)
Me.InitializeComponents()
' ...
_ID = _NextID
_NextID = _NextID + 1
End Sub
' ...
End Class
Then... Create a sorted list containing all the IDs :
Public Class MainClass
Private Shared _IDsList As New SortedList(Of Integer, MainClass)
' then edit your New() method :
Public Sub New(...)
Me.InitializeComponents()
' ...
_ID = _NextID
_NextID = _NextID + 1
_IDList.Add(_ID, Me)
End Sub
' ...
End Class
Then create a static function to get a specific instance of MainClass by its ID.
Public Class MainClass
' ...
Public Shared Function GetInstanceByID(ByVal iID As Integer) As MainClass
If _IDList.ContainsKey(iID) Then
Return _IDList.Item(iID)
Else
Return Nothing
End If
End Function
' ...
' And create the appropriate Dispose() method
' the appropriate Clear() method
' the appropriate FormClosing events handlers
' etc. etc. etc.
End Sub
the thing is, we don't know what's the purpose of your MainClass, and why RemoteClass instances have to modify MainClass members (which members by the way ? controls, variables, add/remove controls ?)

How can I access form.aspx from codefile.aspx.vb?

I have a formview on a page called form.aspx and it of course has a code-behind page called form.aspx.vb
The form.aspx.vb file is huge! So I'd like to take the functions out of the form.aspx.vb page and into functions.vb.
My problems is everything goes out of scope.
example....
form.aspx.vb has this...
dim box1, box2, box3 as Textbox
Public Sub initialiseControls()
box1 = Me.Formview1.FindControl("box1")
box2 = Me.Formview1.FindControl("box2")
box3 = Me.Formview1.FindControl("box3")
End Sub
I'd like to take this sub and put it into functions.vb codefile, but everything is out of scope then.
Can someone tell me if this can be done?
Thanks.
Two options:
1) Pass a reference to the Page into every method that needs to use it:
In code behind:
ExTest.ModifyControl(Me.Page)
New class with various methods in:
Public Class ExTest
Public Shared Sub ModifyControl(aPage As System.Web.UI.Page)
Dim tb As TextBox = CType(aPage.FindControl("txthelloWorld"), TextBox)
tb.Text = "Hello World"
End Sub
End Class
2) Extend the code behind as a partial class:
Current code behind (add the Partial keyword):
Partial Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
ModifyControl()
End Sub
End Class
Add a New class:
Partial Public Class WebForm1
Private Sub ModifyControl()
txtGoodbyeWorld.Text = "Goodbye"
End Sub
End Class

Handling Parent Property Event

Is it possible to listen to a parent class' object's event via the property accessor?
What I've tried (a minimal example):
Public Class ParentFoo
Private WithEvents m_bar As EventyObj
Public Property Bar() As EventyObj
Get
Return m_bar
End Get
Set(ByVal value As EventyObj)
m_bar = value
End Set
End Property
End Class
Public Class ChildFoo
Inherits ParentFoo
[...]
Public Sub Bar_OnShout() Handles Bar.Shout
' Some logic
End Sub
End Class
The specific error message I'm getting (VS2005) is "Handles clause requires a WithEvents variable defined in the containing type or one of its base types." Does accessing a private WithEvents variable via a public property strip away the 'WithEvents'?
In ParentFoo:
Public Overridable Sub OnShout() Handles m_bar.Shout
'No Logic Necessary
End Sub
In ChildFoo:
Public Overrides OnShout()
'Logic Here
End Sub
Since ParentFoo will call OnShout when m_bar raises a Shout Event and you override it in ChildFoo, your ChildFoo's OnShout will handle that event.

How do I render the inner properties of my User Control on the page?

I am designing a user control that attempts to create a filter bar with various TextBox or DropDownList elements on the page according to the sample markup below:
<gf:GridFilterBar runat="server">
<filters>
<filter Label="Field1" Type="TextBox" />
<filter Label="Field2" Type="DropDownList" />
</filters>
</gf:GridFilterBar>
Using inspiration from another post, I have created code behind that properly parses this markup and reads in the properties of each intended child control. The issue I am having is when it comes time to actually render this information on the screen. Every control I initialize from within the "New" sub of the "Filter" class never appears on the screen. When I place a breakpoint in the "New" sub and follow what is happening, I can see the Filter.New sub being traversed twice and the values being read in, but nothing else I initialize from within that sub has any effect on the page even though, as far as I can tell, it is all being created successfully. Here is a sample of the code with just the Label property being read:
Imports System
Imports System.Collections
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class GridFilterBar
Inherits System.Web.UI.UserControl
Private _Filters As New FiltersClass(Me)
<PersistenceMode(PersistenceMode.InnerProperty)> _
Public ReadOnly Property Filters() As FiltersClass
Get
Return _Filters
End Get
End Property
Private Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
DDL.Visible = True
End Sub
End Class
Public Class FiltersClass
Inherits ControlCollection
Public Sub New(ByVal owner As Control)
MyBase.New(owner)
End Sub
Public Overrides Sub Add(ByVal child As System.Web.UI.Control)
MyBase.Add(New Filter(child))
End Sub
End Class
Public Class Filter
Inherits HtmlGenericControl
Public Sub New(ByVal GenericControl As HtmlGenericControl)
Label = GenericControl.Attributes("Label")
Dim lit As New Literal
lit.Text = Label.ToString
Me.Controls.Add(lit)
End Sub
Public Property Label As String = String.Empty
Public Overrides Function ToString() As String
Return Me.Label
End Function
End Class
Can anyone spot what I'm doing wrong?
I was able to answer my question. I added an override sub for CreateChildControls in my main class and used a For Each loop to grab the properties set from each newly initialized "Filter"
Protected Overrides Sub CreateChildControls()
For Each filter In Filters
Dim lit As New Literal
lit.Text = filter.Label
Controls.Add(lit)
Next filter
End Sub
This relegated the Filter.New sub to simply grabbing the properties:
Public Sub New(ByVal GenericControl As HtmlGenericControl)
Label = GenericControl.Attributes("Label")
End Sub

Accessing a list from another class vb.net

I have these two classes class FootballAdmin makes use of the import Football from the projects references, what i need to do is in class MainForm is for the updateView method to access the list held by FootballAdmin and display it in the teamSheetListBox, i am unsure how access the list as indicated by ?????
Imports Football
Public Class FootballAdmin
Private fTeam As List(Of FootballTeams)
Public Sub New()
fTeam = New List(Of FootballTeams)
End Sub
Public ReadOnly Property Teams() As List(Of FootballTeams)
Get
Return fTeams
End Get
End Property
End Class
Public Class MainForm
Private fFootballAdmin As FootballAdmin
Public Sub New()
InitializeComponent()
fFootballAdmin = New FootballAdmin
updateView()
End Sub
Private sub updateView()
For each team As String In ????????
teamSheetListBox.Items.Add(team)
Next
End Sub
End Class
Help please!
The big hint I am going to give you is that team in your loop:
For each team As String In ????????
teamSheetListBox.Items.Add(team)
Next
Isn't going to be a String. It will be the same type: FootballTeam as in your FootballAdmin Class. Consider what you have access to in your MainForm that can get you to those types.