.Net: Why we can't access to some properties of a control programmatically in winforms? For example, "Locked" property of a groupbox is not accessible via code. So What Possibly can I do when I want to locked it programmatically ? Using Enabled = False will greyed out all controls within it and this is not what I wanna to be.

5 Answers
5

Do you know what Locked really mean? This isn't a normal property and isn't affecting runtime anyhow, only designer. You probably should go to the problem you're trying to solve. I can assure you: the "Locked" property isn't needed for that.

Well, I do not know that whether you have developed application with Vb6 or not, but there was a control named frame which we could locked it (and also all its child controls within it) so that user could not start entring data. But the form was clear and not grey.
–
odisehMay 15 '10 at 10:32

OK, sorry, but I still think you shouldn't do this, because this may break user's expectation on the behavior of your application.
–
Dmitriy MatveevMay 15 '10 at 12:04

Locked is not a property at all - it is just a value stored in the resource file. Locking the Form control yields a boolean resource value $this.Locked set to true.

Further some properties are attached to controls using IExtenderProvider similar to attached properties in WPF. For example the designer will show a propery ToolTip for all controls after adding a ToolTip control to the designer. To set the tool tip text by code you have to use

this.toolTip1.SetToolTip(this.button1, "A button.");

because there is no ToolTip property for controls.

And there are more mechanisms like ICustomTypeDescriptor that cause different properties to be shown in the designer than the properties that are really defined for the control.

There is a generic solution to disable WinForms controls without graying them but unfortunately I can neither remember nor find it...

If you want to disable your controls without greying them out, the exact procedure to do so can be fairly complicated and depends on the control's type. I'm giving you some pointers below for TextBox, for CheckBox & RadioButton, and for ComboBox controls.

Bear in mind the possibility that this capability is not built uniformly into Winforms for a reason: A control that looks enabled, but is in fact disabled (read-only) will possibly confuse many users of your application, because dealing with your controls won't match their expectations of how Windows controls usually behave.

TextBox

CheckBox (and RadioButton)

Set the CheckBox.AutoCheck property to false.
Note that this also works for RadioButton controls.

Edit: Unfortunately, I cannot retrieve my sources for making a ComboBox read-only right now. However, it's fairly complicated and involves intercepting window messages in WndProc. Perhaps take a look at this article on CodeProject instead.

Don't go altering the ENABLED property with unneeded API calls. When a combobox is disabled it's only disabled for the user, not code-behind. Just attach eventhandlers to reset colors on disabled.
–
riffnlMay 15 '10 at 10:50

As others have already pointed out, what you actually want to do is to make the controls readonly, but except for textboxes and radiobuttons this can be fairly complicated.

Below is an excerpt from some code I've written to handle something like this, but the client wanted cheap rather than perfect so I had some flexibility so it might not work for you. The method is just called by SetControlsReadonly(gb.Controls) (assuming a groupbox called gb).

Private Sub SetControlsReadonly(ByVal ctrls As Windows.Forms.Control.ControlCollection)
For Each ctrl As Control In ctrls
ctrl.Enabled = True ' first enable everything so that it'll all look the same
If TypeOf ctrl Is TextBox Then
CType(ctrl, TextBox).ReadOnly = True
ElseIf TypeOf ctrl Is Button Then
CType(ctrl, Button).Enabled = False
ElseIf TypeOf ctrl Is CheckBox Then
CType(ctrl, CheckBox).AutoCheck = False
ElseIf TypeOf ctrl Is ComboBox Then
ctrl.Enabled = False
if ctrl.Tag IsNot Nothing Then
' call method that hides the combo and instead shows a readonly textbox in the same location containing the same data
End If
ElseIf TypeOf ctrl Is DateTimePicker Then
ctrl.Enabled = False
End If
SetControlsReadonly(ctrl.Controls)
Next
End Sub

You are missing a final Else block where you handle all other control types. If you don't include that, and someone puts a control on a form that your method doesn't know how to handle, it won't get disabled. -- IMO it would be better design to derive your own control classes (from the standard controls) that implement a common interface IHaveReadOnlyProperty (exposing a ReadOnly property). Your method then checks whether a control supports that interface; if so, it sets the exposed ReadOnly property to false; otherwise, it does the next-best thing, ie. it sets Enabled to false.
–
stakxMay 15 '10 at 16:57

Well, I'm not going to say that your design wouldn't be better (especially if starting from scratch), but as I said, the client wanted cheap rather than perfect. However, I disagree regarding the Else, if you add an Else that disables everything else, you have to make sure that you don't have unexpected controls there (For example a tab control, or a groupbox that contains textboxes etc) since otherwise it wouldn't work as expected.
–
Hans OlssonMay 15 '10 at 21:29