Introduction
I've seen a lot of creative ways to make a combo box read only. The best way I have found to do it is is to create an ExtenderProvider
for the combo box inside which you change the dropdownstyle
to simple
and then trap all the keystrokes.
I've found it useful to set a combobox to readonly for the same reasons I like to use readonly on a textbox.
Namely in order to:
- Keep the background color white instead of disabled gray
- Allow my user to copy text out of the combo box (disabling doesn't allow a copy)
- Keep an associated tooltip enabled (disabling a combo box will also disable the associated tooltip)
Background
This code is based on the IExtenderProvider
interface. You may want to Google it! The article also assumes you already know something about trapping keystrokes and the use of hashtables.
Points of Interest
The IExtenderProvider
can be used in all sorts of situations, like, trapping keystrokes in a textbox control. Look for future articles where I'll show an example of that technique.
Using the Code
You'll need to rebuild the project after you add the ReadOnlyComboProvider
class. Then, simply drag one of these from the toolbox onto your form and set the properties via a property window or via code.
To set the readonly property via code, you would do something like:
Me.ReadOnlyComboProvider1.SetReadOnly(myComboBox, True)
Here's the code for the ExtenderProvider:
Option Explicit On
Option Strict On
Option Compare Text
Imports System.ComponentModel
Imports System.Windows.Forms
<Drawing.ToolboxBitmap(GetType(System.Windows.Forms.TextBox)), _
System.ComponentModel.DesignerCategoryAttribute("Code"), _
ProvideProperty("ReadOnly", GetType(Control)), _
ProvideProperty("OrigDropDownStyle", GetType(Control))> _
Public Class ReadOnlyComboProvider
Inherits System.ComponentModel.Component
Implements IExtenderProvider
Friend htProvidedProperties As New Hashtable
Public Function CanExtend(ByVal extendee As Object) As Boolean _
Implements System.ComponentModel.IExtenderProvider.CanExtend
If TypeOf extendee Is ComboBox Then
Return True
Else
Return False
End If
End Function
Private Class ComboBoxProperties
Public IsReadOnly As Boolean = False
Public OrigComboBoxStyle As ComboBoxStyle = ComboBoxStyle.DropDown
End Class
<Category("Read Only Combobox Provider")> _
Sub SetReadOnly(ByVal ctrl As Control, ByVal value As Boolean)
Dim cbo As ComboBox = CType(ctrl, ComboBox)
If value = True Then
cbo.DropDownStyle = ComboBoxStyle.Simple
Else
cbo.DropDownStyle = GetControlFromHashtable(ctrl).OrigComboBoxStyle
End If
GetControlFromHashtable(ctrl).IsReadOnly = value
End Sub
<Category("Read Only Combobox Provider")> _
Function GetReadOnly(ByVal ctrl As Control) As Boolean
Return GetControlFromHashtable(ctrl).IsReadOnly
End Function
<Category("Read Only Combobox Provider")> _
Sub SetOrigDropDownStyle(ByVal ctrl As Control, ByVal value As ComboBoxStyle)
GetControlFromHashtable(ctrl).OrigComboBoxStyle = value
End Sub
<Category("Read Only Combobox Provider")> _
Function GetOrigDropDownStyle(ByVal ctrl As Control) As ComboBoxStyle
Return GetControlFromHashtable(ctrl).OrigComboBoxStyle
End Function
Private Function GetControlFromHashtable(ByVal ctrl As Control) As ComboBoxProperties
If htProvidedProperties.Contains(ctrl) Then
Return DirectCast(htProvidedProperties(ctrl), ComboBoxProperties)
Else
Dim ProvidedProperties As New ComboBoxProperties
AddHandler ctrl.KeyPress, AddressOf KeyPressHandler
htProvidedProperties.Add(ctrl, ProvidedProperties)
Return ProvidedProperties
End If
End Function
Private Sub KeyPressHandler(ByVal sender As Object, ByVal e As KeyPressEventArgs)
Dim cboSender As ComboBox = CType(sender, ComboBox)
If GetControlFromHashtable(cboSender).IsReadOnly = True Then
e.Handled = True
Else
e.Handled = False
End If
End Sub
End Class
History
- 5/22/08 - First version posted.