简体   繁体   English

.net中的类级别的RefreshProperties属性,winforms +错误地刷新了属性网格

[英]RefreshProperties attribute at class level in .net, winforms + incorrectly refreshing property grid

I had a strange problem editing a class in the property grid whereby the property grid would refresh incorrectly. 我在属性网格中编辑类时遇到了一个奇怪的问题,即属性网格将无法正确刷新。

I managed to reduce the problem down to a class with just two properties. 我设法将问题简化为只有两个属性的类。 I've included the code at the end to ease explanation. 为了方便说明,我在最后添加了代码。

It basically boils down to a class with two properties. 它基本上可以归结为具有两个属性的类。 The first of which is expandable (a font). 第一个是可扩展的(字体)。 The class itself is expandable and also implements the CreateInstance method in the type converter. 该类本身是可扩展的,并且还在类型转换器中实现CreateInstance方法。

To see the problem, expand the font, edit, say 'Bold', and tab away. 要查看该问题,请展开字体,进行编辑,说“粗体”,然后移开标签。 Two problems happen: 发生两个问题:

(1) The second property jumps up and ends up in the expanded font property. (1)第二个属性跳转并在扩展的font属性中结束。

(2) The '-' sign of the expanded font changes to a '+'. (2)扩展字体的“-”符号变为“ +”。

The problem goes away by attaching ResfreshProperties(RefreshProperties.All) to the class. 通过将ResfreshProperties(RefreshProperties.All)附加到类中,问题就解决了。

That's great, but I'd like to understand how it fixed the problem. 很好,但是我想了解它是如何解决问题的。 I've had a look in reflector and can't find any examples of RefreshProperties being attached at the class level. 我看过反射器,找不到在类级别附加的RefreshProperties的任何示例。

/// Simple Class ///简单的类

<TypeConverter(GetType(Class1Converter)), _
RefreshProperties(RefreshProperties.All)> _
Public Class Class1

Public Sub New(ByVal font As Font, ByVal image As Image)
    Me.New()
    Me.Image = image
    Me.Font = font
End Sub

Public Sub New()
End Sub

Private _Font As Font = New Font("Arial", 10)
Public Property Font() As Font
    Get
        Return _Font
    End Get
    Set(ByVal value As Font)
        _Font = value
    End Set
End Property

Private _Image As Image
Public Property Image() As Image
    Get
        Return _Image
    End Get
    Set(ByVal value As Image)
        _Image = value
    End Set
End Property

End Class

/// Converter for the class ///该类的转换器

Public Class Class1Converter
Inherits ExpandableObjectConverter

Public Overrides Function GetCreateInstanceSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
    Return True
End Function

Public Overrides Function CreateInstance(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal propertyValues As System.Collections.IDictionary) As Object
    Dim font As Font = TryCast(propertyValues("Font"), Font)
    Dim image As Image = CType(propertyValues("Image"), Image)
    Return New Class1(font, image)
End Function

End Class

/// A button to host the class ///主持课程的按钮

Public Class MyButton
Inherits Button

Private _C As Class1 = New Class1
Public Property C() As Class1
    Get
        Return _C
    End Get
    Set(ByVal value As Class1)
        _C = value
    End Set
End Property

End Class 末级

It sounds like what's happening is a painting bug in the property grid control. 听起来正在发生的是属性网格控件中的绘画错误。 Was the RefreshPropertiesAttribute applied at the property level when the bug occurred? 发生错误时,是否在属性级别应用了RefreshPropertiesAttribute? Does the component implement INotifyPropertyChanged? 组件是否实现INotifyPropertyChanged?

One reason the problem likely goes away is that applying RefreshPropertiesAttribute at the class level is not the way the attribute is supposed to be used. 该问题可能消失的原因之一是,在类级别应用RefreshPropertiesAttribute并不是应该使用该属性的方式。 I'm guessing that by applying it at the class level you're effectively removing it. 我猜想,通过在班级应用它,您可以有效地删除它。 It looks like they left it set as AttributeTargets.All but clearly that's not by design. 看起来他们将其设置为AttributeTargets.All但显然这不是设计使然。

RefreshProperties is kind of a cop-out attribute. RefreshProperties是一种保护属性。 It tells the designer that when the value of this property changes (via the property grid), go re-query every other property on this class. 它告诉设计者,当此属性的值更改时(通过属性网格),请重新查询该类上的所有其他属性。 Obviously that's kind of wasteful, particularly if the property that changed doesn't have any impact on any other properties. 显然,这是一种浪费,特别是如果已更改的属性对任何其他属性都没有任何影响。

If you do have properties that cause changes in other properties, you can use the PropName Changed event pattern. 如果确实具有导致其他属性发生更改的属性,则可以使用PropName Changed事件模式。 In this case, you would raise a FontChanged or ImageChanged event on the class when those properties change. 在这种情况下,当这些属性更改时,您将在类上引发FontChanged或ImageChanged事件。 The Windows Forms designer looks for events with that naming convention and uses them to invalidate the property grid. Windows窗体设计器使用该命名约定查找事件,并使用它们使属性网格无效。

But in the example you gave, those two properties would not invalidate each other and therefore you wouldn't need to invalidate either one in response to the other. 但是在您给出的示例中,这两个属性不会彼此无效,因此您无需使一个属性无效即可响应另一个属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM