只读属性网格

9
我正在编写的应用程序中使用了PropertyGrid,允许用户查看和有时编辑对象实例。有时,用户可能会以读/写模式打开文件,在通过属性网格对文件进行更改。在其他情况下,他们可能会以只读模式打开文件,并且不应通过PropetyGrid对对象进行任何更改。我的类还有通过实现ICustomTypeDescriptor返回的动态属性,因此我确实希望利用PropertyGrid控件内置的灵活性。

似乎没有一种简单的方法可以将Property-grid设置为只读模式。如果我禁用PropertyGrid,则也会防止用户滚动列表。所以我认为最好的方法是在运行时向属性添加ReadOnlyAttributes。还有其他方法吗?


你是完全正确的。你唯一的方法是在你自定义TypeDescriptor发布的每个属性上添加ReadOnly属性。使用MSPG没有灵活的解决方案可以获得一个禁用的PropertyGrid,仍然可滚动并且“属性可选择”。 - Nicolas Cadilhac
5个回答

18

我找到了一个对于那些不关心属性网格被灰掉的人来说非常快速的解决方案。

TypeDescriptor.AddAttributes(myObject, new Attribute[]{new ReadOnlyAttribute(true)});
propertyGrid1.SelectedObject = myObject;

1
这是一个很棒的一行解决方案。 有没有办法在代码中撤消它?我尝试在应用您的代码后查找对象上名为“Readonly”的属性,但似乎没有找到它。 - Roger Bacon
@RogerBacon 你可以用同样的方式撤销它 TypeDescriptor.AddAttributes(myObject, new ReadOnlyAttribute(false)); 这不是很优雅,但仍然有效。 - Shadr
1
禁用的颜色可以通过 DisabledItemForeColor 进行更改。我将其设置为 ControlText,现在它看起来又正常了(不再是灰色的)。 - Xan-Kun Clark-Davis

3
由于您正在实现 ICustomTypeDescriptor,因此无需添加任何属性;您只需要在 PropertyDescriptor 上覆盖 IsReadOnly。我认为编写一个中间类型应该很简单,它通过 ICustomTypeDescriptorTypeConverter 模拟包装类型,但始终返回只读的 PropertyDesciptor 实例?如果您想要一个示例,请告诉我(尽管这不是简单的)。
您还可以检查一下是否有类似这样的内置功能。

是的,这就是我所思考的,但希望有更简单的方法。实际问题是我的类有时是只读的,而有时不是。不如在基础类型中添加一个布尔属性,让ICustomTypeDescriptor.GetProperties()检查它是否应该返回可编辑或只读属性,而不是创建一个单独的只读包装器类型? - Eric Anastas

1

最終我繼承了PropertyGrid,當選擇屬性時選擇父類別。

簡單且不需要使用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;
            }
        }
    }
}

是的,对我来说足够好用!简单而有效。 - AHowgego

0
我的建议是编写一个自定义控件,该控件继承自PropertyGrid控件,在该自定义控件中,具有只读的布尔值,并覆盖一些内容并检查,如果(只读)则取消操作。

0

我遇到了这个问题。我想要一个只读但不是灰色的控件。

从属性网格控件继承并创建自己的只读版本,通过添加以下代码来重写键盘按键:

#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

你忘了提到必须实现IMessageFilter接口。无论如何,这个解决方案并不起作用,因为它不能防止用户单击或双击下拉框并以此改变值。 - NinjaCross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接