Change the defaultValue of A custom control property - vb.net

I created a number of custom controls but still struggling mastering the interface.
For uniformity besides creating custom proerties I also want to change some base properties of the custom control I tried following code
Protected Overrides Sub OnControlAdded(e As ControlEventArgs)
Me.AutoCompleteMode = AutoCompleteMode.Suggest
Me.AutoCompleteSource = AutoCompleteSource.ListItems
MyBase.OnControlAdded(e)
End Sub
That however does not work when I drop the custom control on a form, I suppose the solution lies with adding the attribute and overriding the property.
I found an answer to this for C# but did not succeed to understand/translate it for vb.net

Since those properties are not overridable, try using the Shadows modifier instead:
Public Class MyComboBox
Inherits ComboBox
Public Sub New()
Me.AutoCompleteMode = AutoCompleteMode.Suggest
Me.AutoCompleteSource = AutoCompleteSource.ListItems
End Sub
<DefaultValue(AutoCompleteMode.Suggest)> _
Public Shadows Property AutoCompleteMode As AutoCompleteMode
Get
Return MyBase.AutoCompleteMode
End Get
Set(value As AutoCompleteMode)
MyBase.AutoCompleteMode = value
End Set
End Property
<DefaultValue(AutoCompleteSource.ListItems)> _
Public Shadows Property AutoCompleteSource As AutoCompleteSource
Get
Return MyBase.AutoCompleteSource
End Get
Set(value As AutoCompleteSource)
MyBase.AutoCompleteSource = value
End Set
End Property
End Class
Please note though, the DefaultValue attribute probably doesn't do what you think it does: it doesn't actually set a default value of that property. All it is used for is to tell the PropertyGrid what the default value for the property is, and if it matches it, it won't make it bold in the PropertyGrid view and it won't serialize the value in the designer file.

Related

Force Inherited ComboBox' DropDownStyle Property to DropDown

In VB.NET (WinForms), how to force a control that inherits ComboBox to only allow DropDown for its DropDownStyle property?
The DropDownStyle property is not Overridable, that limits the amount of forcing your can do. The approach that .NET Framework takes is to just hide the property. Similar to:
Private Const DefaultStyle As ComboBoxStyle = ComboBoxStyle.DropDown
Public Sub New()
MyBase.DropDownStyle = DefaultStyle
End Sub
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never)>
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
Public Overloads Property DropDownStyle As ComboBoxStyle
Get
Return MyBase.DropDownStyle
End Get
Set(value As ComboBoxStyle)
MyBase.DropDownStyle = DefaultStyle
End Set
End Property
The Browsable attribute hides the property from the designer, the EditorBrowsable attribute hides it from the text editor, the DesignerSerializationVisibility ensures it is not written to the InitializeComponent() method.
But that doesn't otherwise stop client code, if it really wants to then it can cast to ComboBox and bypass your property setter, still assigning the MyBase.DropDownStyle property to an arbitrary value. The liability of Overloads only hiding the base member and not overriding it. Technically you can still defeat that by overriding CreateParams but the property is used too often in the ComboBox code to make that truly effective. This is as good as it gets. Good enough for the framework.

VB.NET Forms ListBox doesn't display DataSource

I'm trying to link my ListBox to an ObservableCollection.
Here's my class for defining mods:
Public Class TroveMod
Private m_FileName As String
Private m_Enabled As Boolean
Public Property FileName() As String
Get
Return m_FileName
End Get
Set(value As String)
m_FileName = value
End Set
End Property
Public Property Enabled() As Boolean
Get
Return m_Enabled
End Get
Set(value As Boolean)
m_Enabled = value
End Set
End Property
Public ReadOnly Property ModName()
Get
Return Path.GetFileNameWithoutExtension(FileName)
End Get
End Property
End Class
And this is the actual Property ModList:
Public Property ModList() As ObservableCollection(Of TroveMod)
Get
Return m_ModList
End Get
Set(value As ObservableCollection(Of TroveMod))
m_ModList = value
End Set
End Property
I add items using:
Private Sub AddMod(file__1 As String, enabled As Boolean)
If File.Exists(file__1) Then
ModList.Add(New TroveMod() With { _
.FileName = file__1, _
.Enabled = enabled _
})
End If
End Sub
Everytime I want to add something to this Collection using AddMod, it won't show off in my listbox :/ I added an ModListBindingSource to the ListBox and set the DisplayMember and ValueMember to ModName but it still won't work. I also got a status label, which says, that it successful added the mods to the collection but it simply won't show them in the ListBox. Did I miss something?
An ObservableCollection is not quite what you want - this would allow your code to see changes to the collection via events. For instance, if there were several actors adding items to the collection and you wanted to know that. In this case, since 'local' code is adding items, it is not needed.
It is also not clear how the collection is mapped to the ListBox as the DataSource. Try this:
Public Class Form...
Private myList As New BindingList(Of TroveMod)
Sub Form_Load(....
theListBox.DataSource = myList
theListBox.DisplayMember = "ModName"
Now, as you add things to the BindingList they will appear in theListBox. If an item changes though (e.g. the Name), that change will not show up without a little more work, but as these are file names that seems unlikely.
The form property is not needed unless an external class also needs access to the collection/BindingList; in that case, you probably do not want need a setter.

.NET Designer issues shadowing properties as readonly in inherited controls

I am trying to create custom controls to provide some consistency to the design of an application. However when I shadow a property with a readonly alternatvie, I get designer errors at build time. Now I can delete the offending lines of code in the designer file and continue to build and run my application but firstly this is irritating, and secondly it tells me that I must be doing something fundamentally wrong!
Here's an example of a control that overrides datagridview
Class standardDataGridView
Inherits DataGridView
Public Sub New()
MyBase.New()
Me.RowHeadersVisible = False
MyBase.SelectionMode = DataGridViewSelectionMode.FullRowSelect
MyBase.MultiSelect = False
Me.ReadOnly = True
Me.BackgroundColor = Color.White
Me.AllowUserToDeleteRows = False
Me.AllowUserToResizeRows = False
Me.AllowUserToAddRows = False
End Sub
Public Shadows ReadOnly Property SelectionMode As DataGridViewSelectionMode
Get
Return MyBase.SelectionMode
End Get
End Property
Public Shadows ReadOnly Property MultiSelect As Boolean
Get
Return MyBase.MultiSelect
End Get
End Property
End Class
In the first build after adding one of these controls to a form, or after changing any properties, the following lines get added to the designer file by Visual Studio:
Me.standardDataGridView1.MultiSelect = False
Me.standardDataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
Which results in the following build errors
Property 'MultiSelect' is 'ReadOnly'.
Property 'SelectionMode' is 'ReadOnly'
As I say... I can remove the lines that Visual Stuido added, and continue, but where have I gone wrong to be getting this problem?
Try telling the forms designer to not serialize those properties:
Imports System.ComponentModel
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows ReadOnly Property SelectionMode As DataGridViewSelectionMode
Get
Return MyBase.SelectionMode
End Get
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows ReadOnly Property MultiSelect As Boolean
Get
Return MyBase.MultiSelect
End Get
End Property
Make sure to rebuild your solution.

Override Textbox Properties In VB.NET

It is possible to override textbox properties like selectionstart property
Yes you can by creating your own textbox class, such as
Class MyTextBox
Inherits TextBox
Public Shadows Property SelectionStart As Integer
Get
' Get Code
End Get
Set(ByVal value As Integer)
' Set code
End Set
End Property
End Class
You can create your own custom control that inherits from the textbox control and override whatever events you need to.
Here is some guidance from MSDN.
SelectionStart property is not marked as virtual, so you can not override it. Other properties that are virtual or overridable can be overridden.

Custom CollectionEditor never triggers a property's "set" method

I am trying to implement a way of persisting a collection in a custom settings class. I have successfully created the settings class (inheriting ApplicationSettingsBase) and can save properties using the built-in editors on a PropertyGrid, but my custom implementation of a property grid for collections doesn't persist any of the values I add. Here's my code:
Imports System.Configuration
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.ComponentModel.Design
Public Class CustomSettings
Inherits ApplicationSettingsBase
<UserScopedSetting()> _
<DefaultSettingValue("White")> _
Public Property BackgroundColor() As Color
Get
BackgroundColor = Me("BackgroundColor")
End Get
Set(ByVal value As Color)
Me("BackgroundColor") = value
End Set
End Property
<UserScopedSetting()> _
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
<Editor(GetType(CustomStringCollectionEditor), GetType(UITypeEditor))> _
Public Property EmailAddresses() As Collection
Get
EmailAddresses = Me("EmailAddresses")
End Get
Set(ByVal value As Collection)
Me("EmailAddresses") = value
End Set
End Property
End Class
Public Class CustomStringCollectionEditor
Inherits CollectionEditor
Public Sub New()
MyBase.New(GetType(Collection))
End Sub
Protected Overrides Function CreateInstance(ByVal itemType As System.Type) As Object
Return String.Empty
End Function
Protected Overrides Function CreateCollectionItemType() As System.Type
Return GetType(String)
End Function
End Class
I set a breakpoint on the Set methods for both the BackgroundColor property and the EmailAddresses property. The BackgroundColor property works as it should - it breaks on the Set statement and stores the property correctly. But when I close the custom CollectionEditor dialog, the EmailAddresses "Set" method is never called. How can I get my custom editor to actually save the property once it's done being edited?
I think I fixed it (with help from this question). I added an override to the EditValue function in my custom editor. Here is the code:
Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
Dim result As Object = MyBase.EditValue(context, provider, value)
DirectCast(context.Instance, CustomSettings).EmailAddresses = DirectCast(result, List(Of String))
Return result
End Function
I also moved from a collection to a list - I read somewhere that was a safer way to go. I also added a constructor to my CustomSettings class that set the EmailAddresses property to a new List(Of String) if it was unset to begin with. I found that the first time it ran, I could edit the list and add items, but they wouldn't be persisted:
Public Sub New()
If Me("EmailAddresses") Is Nothing Then
Me("EmailAddresses") = New List(Of String)
End If
End Sub
And now it's all working like it should. But if this isn't the best way or there's an easier way to do it, please chime in.