I create a class based on other class. I'm try to assign the class a value in its constructor, but get an error.
Error 1 'Me' cannot be the target of an assignment.
is there a way to solve it..? Here is a code I've created
Public Class tabelDSN
Inherits DataTable
Public Sub New(ByVal dt As DataTable)
Me = dt.Copy()
End Sub
Default Public ReadOnly Property rw(ByVal idx) As DataRow
Get
Return Me.Rows(idx)
End Get
End Property
End Class
You could make your tabelDSN class be a wrapper for the DataTable class, by removing the Inherits and adding a private DataTable field to hold the constructor parameter. The code would look like this:
Public Class tabelDSN
Private _dt as DataTable
Public Sub New(ByVal dt As DataTable)
_dt = dt.Copy()
End Sub
Default Public ReadOnly Property rw(ByVal idx) As DataRow
Get
Return _dt.Rows(idx)
End Get
End Property
End Class
Related
I created a class that inherits button in win forms
How can i create a Browsable property with type dictionary ?
here is my code
but i didn't find it in properties menu
vb.net
<Browsable(True)>
Property Set_ddn() As Dictionary(Of TextBox, String)
Get
Return ddn
End Get
Set(ByVal value As Dictionary(Of TextBox, String))
ddn = value
End Set
End Property
how can i make it browsable ?
or what should i use instead of dictionary?
or another solution
i found the answer here (C#)
https://stackoverflow.com/a/42829336/1543991
rewrite code for vb.net
You should write your own type descriptor by deriving from CustomTypeDescriptor or implementing ICustomTypeDescriptor. Here is an example:
MyPropertyDescriptor
Provide a custom description for a property. Here I override Attributes property to provide a new list of attributes for property. For example I check if the property has [Category("Extra")], I also added a [Browsable(false)] to its attribute collection.
Imports System
Imports System.ComponentModel
Imports System.Linq
Public Class MyPropertyDescriptor
Inherits PropertyDescriptor
Private o As PropertyDescriptor
Public Sub New(ByVal originalProperty As PropertyDescriptor)
MyBase.New(originalProperty)
o = originalProperty
End Sub
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Return o.CanResetValue(component)
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return o.GetValue(component)
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
o.ResetValue(component)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
o.SetValue(component, value)
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return o.ShouldSerializeValue(component)
End Function
Public Overrides ReadOnly Property Attributes As AttributeCollection
Get
Dim attributes = MyBase.Attributes.Cast(Of Attribute)().ToList()
Dim category = attributes.OfType(Of CategoryAttribute)().FirstOrDefault()
If category IsNot Nothing AndAlso category.Category = "Extra" Then attributes.Add(New BrowsableAttribute(False))
Return New AttributeCollection(attributes.ToArray())
End Get
End Property
Public Overrides ReadOnly Property ComponentType As Type
Get
Return o.ComponentType
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return o.IsReadOnly
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return o.PropertyType
End Get
End Property
End Class
MyTypeDescriptor
Used to provide a list of custom property descriptors for a type.
Imports System
Imports System.ComponentModel
Imports System.Linq
Public Class MyTypeDescriptor
Inherits CustomTypeDescriptor
Private original As ICustomTypeDescriptor
Public Sub New(ByVal originalDescriptor As ICustomTypeDescriptor)
MyBase.New(originalDescriptor)
original = originalDescriptor
End Sub
Public Overrides Function GetProperties() As PropertyDescriptorCollection
Return Me.GetProperties(New Attribute() {})
End Function
Public Overrides Function GetProperties(ByVal attributes As Attribute()) As PropertyDescriptorCollection
Dim properties = MyBase.GetProperties(attributes).Cast(Of PropertyDescriptor)().[Select](Function(p) New MyPropertyDescriptor(p)).ToArray()
Return New PropertyDescriptorCollection(properties)
End Function
End Class
MyTypeDescriptionProvider
Used to connect MyTypeDescriptor to a class using TypeDescriptionProvider attribute.
Imports System
Imports System.ComponentModel
Public Class MyTypeDescriptionProvider
Inherits TypeDescriptionProvider
Public Sub New()
MyBase.New(TypeDescriptor.GetProvider(GetType(Object)))
End Sub
Public Overrides Function GetTypeDescriptor(ByVal type As Type, ByVal o As Object) As ICustomTypeDescriptor
Dim baseDescriptor As ICustomTypeDescriptor = MyBase.GetTypeDescriptor(type, o)
Return New MyTypeDescriptor(baseDescriptor)
End Function
End Class
MySampleClass
Contains a property decorated with [Category("Extra")]. So Property2 will not be visible in property grid. (In visual studio or collection editor or even run-time property grid)
<TypeDescriptionProvider(GetType(MyTypeDescriptionProvider))>
Public Class MySampleClass
Public Property Property1 As Integer
<Category("Extra")>
Public Property Property2 As String
End Class
MyComplexComponent
Contains a collection of MySampleClass. So you can see behavior of MySampleClass in collection editor.
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Public Class MyComplexComponent
Inherits Component
Public Sub New()
MySampleClasses = New Collection(Of MySampleClass)()
End Sub
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Property MySampleClasses As Collection(Of MySampleClass)
End Class
How to call a method from within a property which is declared as a List(Of T), when new values were added into Property?
In my example you see a class called Something, another class called MyClass with a Property Things As List(Of Something), and my main form where a new instance of MyClassis made, then some values has been added into its' Things Property by using the Add (or AddRange) method of generic lists.
My question: how to trigger DoSomeAction() method every time Things property values change (added or removed by using Add, Addrange, Remove, etc. methods)?
Public Partial Class MainForm ' System.Windows.Forms.Form
Dim newMyClass As New MyClass
newMyClass.Things.Add(New Something())
newMyClass.Things.AddRange(New Something() {New Something(), New Something()})
End Class
Public Class MyClass
Private thingsValue As List(Of Something)
'
Public Property Things() As List(Of Something)
Set(value As List(Of Something))
thingsValue = value
DoSomeAction()
End Set
Get
Return thingsValue
End Get
End Property
'
Private Sub DoSomeAction()
'[inside method DoSomeAction()]
End Sub
'
Public Sub New()
thingsValue = New List(Of Something)
End Sub
End Class
Public Class Something
'[inside class Something]
End Class
I would like to write a nested class into an existing class of my own. But I can't find how because I have no idea how this is really called.
What do I mean by nested class? With a table dt from the DataTable class, I can write dt.Columns.add(). Columns would be property of the main class and add would be a method from a nested class.
Any suggestions?
That is not a nested class, it's simply a class. The Columns property is of the type DataColumnCollection that has a public method called Add. To build your own in a similar fashion it would simply be:
Public Class MyFirstClass
Public Sub New()
End Sub
Dim _second As New MySecondClass()
Public Property Second() As MySecondClass
Get
Return _second
End Get
Set(ByVal Value As MySecondClass)
_second = Value
End Set
End Property
End Class
Public Class MySecondClass
Public Sub New()
End Sub
Public Sub MySecondClassMethod()
'Do something
End Sub
End Class
This would then be called in some other class or functionality like:
Dim x as New MyFirstClass()
x.Second.MySecondClassMethod()
I’m working on some partial classes but I can’t figure out how to do it.
This is my classes:
Partial Public Class Form
Private InfoField() As Info
Private FormgroupField() As FormGroup
Private tittle As String
Public Property Info() As Info()
Get
Return Me. InfoField
End Get
Set
Me. InfoField = value
End Set
End Property
Public Property FormGroup() As FormGroup()
Get
Return Me.GromGroupField
End Get
Set
Me.FormGroupField = value
End Set
End Property
Public Property tittle() As String
Get
Return Me.tittleField
End Get
Set
Me.tittleField = value
End Set
End Property
End class
Partial Public Class Info
Private ChangeFormField() As ChangeForm
Private formYearField() As FormYea
Private idField As String
Public Property ChangeForm() As ChangeForm()
Get
Return Me.changeFormField
End Get
Set
Me.changeFormField = value
End Set
End Property
Public Property FormYear() As FormYear()
Get
Return Me.formYearField
End Get
Set
Me.formYearField = value
End Set
End Property
Public Property id() As String
Get
Return Me.idField
End Get
Set
Me.idField = value
End Set
End Property
End Class
Partial Public Class ChangeForm
Private idField As String
Private valueField As String
<properties goes here>
End Class
Partial Public Class FormYear
Private idField As String
Private valueField As String
<properties goes here>
End Class
And for the class FormGroup the organization is the same.
I want to build partial classes to extend these classes, so when I use all this classes in another project I only have to deal with (see) the topmost class (Form) and not the other classes (like Info and FormGroup. This is what I like to do:
Partial Public Class Form
Public Sub Init()
Me.Info = New Info
Me.FormGroup = New FormGroup
Me.Info.Init()
Me.FormGroup.Init()
End Sub
End Class
Partial Public Class Info
Public Sub Init()
Me.FormYear = New FormYear
Me.ChangeForm = New ChangeForm
Me.changeForm.Init()
End Sub
But I can’t write
Me.Info = New Info
Me.FormGroup = New FormGroup
because it is arrays with classes. How can I do it in my Form and Info class?
Thanks in advance.
You must first create an array, then loop over the array and assign each element. Also, unless you have a good, strong reason, do this in the constructor rather than a separate init method.
Public Class Form
Public Sub New()
'In VB, you give the max index, not the length.
'I prefer listing this as (whatever I want for length) - 1
Me.Info = New Info(size - 1) {}
For i = 0 to size - 1
Me.Info(i) = New Info()
Next
'similarly for other fields
End Sub
End Class
Alternatively, if you find yourself with a lot of array fields, and they all have default constructors, you could create a FixedCollection class that would encapsulate the repetitive initialization code.
Public Class FixedCollection(Of T As New)
Inherits Collection(Of T)
Public Sub New(ByVal size As Integer)
MyBase.New(New T(size - 1) {})
For i = 0 to size - 1
Me.Items(i) = New T()
Next
End Sub
'alternate constructors if you need additional initialization
'beyond construction of each element
Public Sub New(ByVal size As Integer, ByVal creator As Func(Of T))
MyBase.New(New T(size - 1) {})
If creator Is Nothing Then Throw New ArgumentNullException("creator")
For i = 0 to size - 1
Me.Items(i) = creator()
Next
End Sub
'this overload allows you to include the index in the collection
'if it would matter to creation
Public Sub New(ByVal size As Integer, ByVal creator As Func(Of Integer, T))
MyBase.New(New T(size - 1) {})
If creator Is Nothing Then Throw New ArgumentNullException("creator")
For i = 0 to size - 1
Me.Items(i) = creator(i)
Next
End Sub
'other collection overrides as needed here
End Class
EDIT: Added constructor overloads for when an element constructor is not enough.
If you only use the constructors with a creator parameter, you could remove the New constraint on T.
Use the overloads as follows:
Public Class Form
Private InfoField As New FixedCollection(Of Info)(10,
Function()
Dim ret As New Info()
ret.Init()
End Function)
End Class
Based on your comments, it seems like the Init methods are an unfortunate necessity. If possible, I would recommend that you find a way to get the generated constructor changed to call this method (defined in the generated code using partial methods) for you rather than forcing you to call it yourself.
You can initialize an Array of a Class like this:
Public FieldTypes As FieldTypeInfo() =
{
New FieldTypeInfo("Byte", 1),
New FieldTypeInfo("Int16", 2),
New FieldTypeInfo("Int32", 3),
New FieldTypeInfo("Integer", 3),
New FieldTypeInfo("Int64", 4),
New FieldTypeInfo("UInt16", 5),
New FieldTypeInfo("UInt32", 6),
New FieldTypeInfo("UInteger", 6),
New FieldTypeInfo("UInt64", 7)
}
I have two classes:
class class2
inherits class1
public sub modify()
'modify property of class1
end sub
end class
How can I modify class1 in a sub in class2?
You just call it. Example:
Public Class class1
Private _Value As String = String.Empty
Property Value() As String
Get
Return _Value
End Get
Set(ByVal value As String)
_Value = value
End Set
End Property
End Class
Public Class class2
Inherits class1
Public Sub modify()
Value = "modified"
End Sub
End Class
And to show it works:
Dim c2 As New class2
c2.modify()
MessageBox.Show(c2.Value)
You are asking about properties, note that only protected and public properties are visible to inherited classes.
You need the MyBase keyword when you are overriding an existing function in the parent class. Other protected or public properties or functions can be accessed regulary without any special keyword.
One tip I wanted to add to the above comments regarding accessing base class info is where you have a base class without a default contructor or want to use a specific constructor This is a good opportunity to use Mybase. You have to call the constructor before any additional actions take place in this scenario.
Public Class MyClass
Inherits baseClass
Public Sub New()
mybase.new("Oranges")
End Sub
End Class
Public Class baseClass
Private _someVariable as String
Public Sub New(byval passedString as string)
_someVariable = passedString
End Sub
End Class