I'm using a PropertyGrid in an application I am writing to allow users to view and sometimes edit instances of my objects. Sometimes the user may have a 开发者_开发问答file open in read/write mode where they can make changes to the file through the property grid. In other cases they may have a file open in read only mode, and should not be able to make any changes to the objects through the PropetyGrid. My classes also have dynamic properties which are returned by implementing ICustomTypeDescriptor. Which is why I really want to take advantage of the built in flexibility of a PropertyGrid control.
There doesn't seem to be an easy way to set a Property-grid to a read only mode. If I disable a PropertyGrid this also prevents the user from scrolling the list. So I'm thinking the best way to do this is to add ReadOnlyAttributes to the properties at run-time. Is there some other way?
I have found a very quick solution for thoses who do not care about the propertygrid being grayed out.
TypeDescriptor.AddAttributes(myObject, new Attribute[]{new ReadOnlyAttribute(true)});
propertyGrid1.SelectedObject = myObject;
Since you are implementing ICustomTypeDescriptor
there is no need to add any attributes; you can just override IsReadOnly
on the PropertyDescriptor
. I'm thinking it should be pretty simple to write an intermediary type that mimics (via ICustomTypeDescriptor
and TypeConverter
) a wrapped type but always returns readonly PropertyDesciptor
instances? Let me know if you want an example (it isn't trivial though).
You might also want to check whether something like this offers it built it.
My advice would be to write a custom control that inherits from the propertygrid control, and in that custom control, have a boolean value of readonly, and then override some things and check, if(readonly) then cancel the action
I ran into this one. I wanted a control that was read only but not grayed out.
Inherit from the property grid control and create your own read only version by adding the following code to override key presses
#Region "Non-greyed read only support"
Private isReadOnly As Boolean
Public Property [ReadOnly]() As Boolean
Get
Return Me.isReadOnly
End Get
Set(ByVal value As Boolean)
Me.isReadOnly = value
End Set
End Property
Protected Overrides Function ProcessDialogKey(ByVal keyData As Keys) As Boolean
If Me.isReadOnly Then Return True
Return MyBase.ProcessDialogKey(keyData)
End Function
Public Function PreFilterMessage(ByRef m As Message) As Boolean
If m.Msg = &H204 Then 'WM_RBUTTONDOWN
If Me.isReadOnly Then Return True
End If
Return False
End Function
#End Region
I ended up inheriting from PropertyGrid and select the parent category whenever a property is selected.
Simple and no need to use TypeDescriptor.
public class ReadOnlyPropGrid : PropertyGrid
{
public ReadOnlyPropGrid()
{
this.ToolbarVisible = false; // categories need to be always visible
}
protected override void OnSelectedGridItemChanged(SelectedGridItemChangedEventArgs e)
{
if (e.NewSelection.GridItemType == GridItemType.Property)
{
if (e.NewSelection.Parent != null && e.NewSelection.Parent.GridItemType == GridItemType.Category)
{
this.SelectedGridItem = e.NewSelection.Parent;
return;
}
}
}
}
精彩评论