Force Inherited ComboBox' DropDownStyle Property to DropDown - vb.net

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.

Related

Keys missing as designer property of UC

I'm starting to code a custom keyboard for my company, and I'm not sure why I don't have access to all keys in the designer. This seems like it should be very simple. One example key is Escape, but there are others.
New Project ->
right-click -> add new -> UserControl
UserControl1.vb
Public Class UserControl1
Private _myKey As Keys
Public Property MyKey() As Keys
Get
Return _myKey
End Get
Set(ByVal value As Keys)
_myKey = value
End Set
End Property
End Class
Build -> Form1 designer -> Drop UserControl1 onto Form1.vb
Form1.vb [Design]
->Select UserControl11
Properties -> Misc -> MyKey
try to set to Keys.Escape (or any number of others).
The available keys list is fairly verbose, but absolutely not complete.
What is the right way to do this? I would much prefer find a solution that allows me to do this via the designer than having to do this on load programmatically.
The below works, but again, I don't understand why I can't do this in the designer:
Public Class Form1
Public Sub New()
InitializeComponent()
UserControl11.MyKey = Keys.Escape
End Sub
End Class
I know I can define my own Enum and get it, but that's so much time for something that should probably just work with .net. What am I doing wrong here?
First off, great question with clear repro directions.
It's strange behavior for sure. Maybe someone has an explanation.
This workaround might do the trick though
Public Class UserControl1
Private _keyCode As Integer
Public Property KeyCode As Integer
Get
Return _keyCode
End Get
Set(ByVal value As Integer)
_keyCode = value
End Set
End Property
Public Property MyKey As Keys
Get
Return CType(_keyCode, Keys)
End Get
Set(ByVal value As Keys)
_keyCode = value
End Set
End Property
End Class
You can set KeyCode in the property pages to the integer value of Escape in System.Windows.Forms.Keys for instance, which is 27.
at which point, MyKey actually displays Escape. Not sure why it doesn't show up in the list.
The values can be found on MSDN: https://msdn.microsoft.com/en-us/library/system.windows.forms.keys(v=vs.71).aspx
Note: you can also just type Escape in MyKey. Adding KeyCode gives a nice other option though.
If you look at the System.Windows.Forms.Keys Enum in a decompiler, you will see that it is decorated with both a TypeConverter and Editor attribute. These attributes are controlling what you can do in the WinForms designer as they are inherited by your MyKey property.
<Flags, TypeConverter(GetType(KeysConverter)), Editor("System.Windows.Forms.Design.ShortcutKeysEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", GetType(UITypeEditor)), ComVisible(True)> _
Public Enum Keys
If you want to present the Keys Enum with the default Enum UI, you will need to decorate your property with its own TypeConverter and Editor attributes that tell the designer to use the default editor and the Enum type converter (this converter allows conversion between the Enum and String representation) instead of the ones declared on the Keys type.
<System.ComponentModel.TypeConverterAttribute(GetType(System.ComponentModel.EnumConverter))>
<System.ComponentModel.Editor(GetType(UITypeEditor), GetType(UITypeEditor))>
Public Property MyKey() As Keys

Change the defaultValue of A custom control property

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.

.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.

Create a DataGridView with a Caption (Embed in GroupBox)

I have a DataGridView and I want to put it into a GroupBox. In VB6 it looked like this:
So it is just a MsFlexGrid wrapped by a GroupBox. I've absolutely no idea, how to implement that in VB.NET.
I'd let it inherit from DataGridView, so it is a Control, and it has every Property of the DataGridView by default.
Public Class CaptionedDataGridView
Inherits DataGridView
There would also have to be a GroupBox:
Private xGroupBox as GroupBox
The text property would be overrided by the text of the group box as well as some size and placement properties (Top, Left, Width, Height)
Public Overrides Property Text As String
Get
Return xGroupBox.Text
End Get
Set(ByVal value As Integer)
xGroupBox.Text = value
End Set
End Property
Finally, if I'd create a new CaptionedDataGridView somewhere it should draw itself with the GroupBox sorrounded. How do I get from where I am right now to where I want to be?
I think you have to do that the other way around. Inherit from the GroupBox and add the DataGridView to it.
Simple example:
Public Class MyGrid
Inherits GroupBox
Private _Grid As DataGridView
Public Sub New()
_Grid = New DataGridView()
_Grid.Dock = DockStyle.Fill
Me.Controls.Add(_Grid)
End Sub
ReadOnly Property Grid As DataGridView
Get
Return _Grid
End Get
End Property
End Class
Of course, you don't have to do this as a custom control. You can just put a GroupBox on your form and add the DataGridView to it with that same DockStyle.Fill property.

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.