1

我正在尝试按类别属性列出一些属性名称并将它们放入变量中。 例如,获取“属于”类别外观的所有属性名称并将它们放入变量中。

我有一个类似的示例可以重置特定属性,但是我必须一一添加它们,这是我想避免的。

Dim _Form As Form = CType(Me, Form)
Dim ListOfPropertyNames As New List(Of String) From {"BackColor", "ForeColor"}
For Each _Property In ListOfPropertyNames
    Dim _PropertyDescriptor As PropertyDescriptor = TypeDescriptor.GetProperties(_Form)(_Property)
    If _PropertyDescriptor.CanResetValue(_Form) Then
        If _PropertyDescriptor.GetValue(_Form) IsNot Nothing Then
            _PropertyDescriptor.ResetValue(_Form)
        End If
    End If
Next
4

1 回答 1

0

您的问题有四种可能的情况(我能想到):

  1. (更有可能)获取按Categoryand排序的属性列表DisplayName,如果PropertyDescriptor.CanResetValue()方法返回肯定结果,则重置属性。最后,通过插入一个子句进行
    过滤。Category.Where

  2. 获取属于某些预定义类别的属性列表,并重置所有值与DefaultValueAttribute不同的属性,检查PropertyDescriptor.CanResetValue()方法结果。

  3. 与上面相同,但还添加了要重置的特定属性列表。

  4. 获取属于某些预定义类别的属性列表并重置所有属性,无论怎么PropertyDescriptor.CanResetValue()想。

第一种情况:
使用 LINQ,查询TypeDescriptor以构建按和排序的PropertyDescriptor元素列表。 检查结果并将属性值重置为默认值(如果已更改)。CategoryDisplayName
PropertyDescriptor.CanResetValue()

Dim PropertyCollection As List(Of PropertyDescriptor) = TypeDescriptor.
                                                        GetProperties(_Form).
                                                        OfType(Of PropertyDescriptor).
                                                        OrderBy(Function(item) item.Category).
                                                        ThenBy(Function(item) item.DisplayName).
                                                        ToList()

For Each _PropertyDescriptor As PropertyDescriptor In PropertyCollection
    If _PropertyDescriptor.CanResetValue(_Form) Then
        If _PropertyDescriptor.GetValue(_Form) IsNot Nothing Then
            _PropertyDescriptor.ResetValue(_Form)
        End If
    End If
Next

与类别过滤器相同:

Dim PropertyCollection As List(Of PropertyDescriptor) = TypeDescriptor.
                                                        GetProperties(_Form).
                                                        OfType(Of PropertyDescriptor).
                                                        OrderBy(Function(item) item.Category).
                                                        ThenBy(Function(item) item.DisplayName).
                                                        Where(Function(item) item.Category = "Appearance").
                                                        ToList()

同样,使用以下命令对 Properties 列表进行Category分组GroupBy()

Dim _Form As Form = Me

Dim PropertyCollection As List(Of IGrouping(Of String, PropertyDescriptor)) = TypeDescriptor.
                                  GetProperties(_Form).
                                  OfType(Of PropertyDescriptor).
                                  OrderBy(Function(item) item.Category).
                                  ThenBy(Function(item) item.DisplayName).
                                  GroupBy(Function(item) item.Category).
                                  ToList()

'Extract one Category. It could also be a second For Each loop.
Dim CategoryPropertyList As List(Of PropertyDescriptor) = PropertyCollection.
                                                          SelectMany(Function(grp) grp).
                                                          Where(Function(prop) prop.Category = "Appearance").
                                                          ToList()

For Each _PropertyDescriptor As PropertyDescriptor In CategoryPropertyList

    If _PropertyDescriptor.CanResetValue(_Form) Then
        If _PropertyDescriptor.GetValue(_Form) IsNot Nothing Then
            _PropertyDescriptor.ResetValue(_Form)
        End If
    End If
Next

第二种情况:
使用 LINQ,查询TypeDescriptor以构建PropertyDescriptor与预定义类别列表相关的元素列表。
检查PropertyDescriptor.CanResetValue()结果并将属性值重置为默认值(如果已更改)。

Dim _Form As Form = CType(Me, Form)
Dim ListOfCategoryNames As New List(Of String) From {"Appearance", "Behavior"}

For Each Category As String In ListOfCategoryNames
    Dim _PropertyCollection As List(Of PropertyDescriptor) = TypeDescriptor.
                                                             GetProperties(_Form).
                                                             OfType(Of PropertyDescriptor).
                                                             Where(Function(item) item.Category = Category).
                                                             ToList()

    For Each _PropertyDescriptor As PropertyDescriptor In _PropertyCollection
        If _PropertyDescriptor.CanResetValue(_Form) Then
            If _PropertyDescriptor.GetValue(_Form) IsNot Nothing Then
                _PropertyDescriptor.ResetValue(_Form)
            End If
        End If
    Next
Next

第三种情况:
与上面相同,但为某些特定属性添加过滤器:

Dim ListOfCategoryNames As New List(Of String) From {"Appearance", "Behavior"}
Dim ListOfPropertyNames As New List(Of String) From {"BackColor", "ForeColor", "AllowDrop", "Enabled"}

For Each Category As String In ListOfCategoryNames
    For Each PropertyName As String In ListOfPropertyNames
        Dim _PropertyDescriptor As PropertyDescriptor = TypeDescriptor.GetProperties(_Form).
                                                        OfType(Of PropertyDescriptor).
                                                        Where(Function(item) item.Category = Category AndAlso
                                                                             item.Name = PropertyName).
                                                        FirstOrDefault()

        If (_PropertyDescriptor IsNot Nothing) AndAlso _PropertyDescriptor.CanResetValue(_Form) Then
            If _PropertyDescriptor.GetValue(_Form) IsNot Nothing Then
                _PropertyDescriptor.ResetValue(_Form)
            End If
        End If
    Next
Next

第四种情况:
使用 LINQ,查询TypeDescriptor构建PropertyDescriptor与预定义类别列表相关的元素列表。
检查DefaultValueAttributeProperty 的 是否为Nothing,因为如果是,PropertyDescriptor.CanResetValue()将跳过它并寻找自定义方法替代来获取结果。由于此处未定义此类方法,因此它将始终返回 false,除非它可以检测到属性已更改。
如果 no 不DefaultValueAttribute存在或PropertyDescriptor.CanResetValue()返回True,则将所有属性值重置为默认值,预先检查该属性是否存在ResetValue()方法。

Dim _Form As Form = CType(Me, Form)
Dim ListOfCategoryNames As New List(Of String) From {"Appearance", "Behavior"}

For Each Category As String In ListOfCategoryNames
    Dim _PropertyCollection As List(Of PropertyDescriptor) = TypeDescriptor.
                                                             GetProperties(_Form).
                                                             OfType(Of PropertyDescriptor).
                                                             Where(Function(item) item.Category = Category).
                                                             ToList()

    For Each _PropertyDescriptor As PropertyDescriptor In _PropertyCollection
        Dim _DefaultAttribute As DefaultValueAttribute = _PropertyDescriptor.
                                                         Attributes.OfType(Of DefaultValueAttribute).
                                                         Where(Function(item) item.IsDefaultAttribute).
                                                         FirstOrDefault

        If (_DefaultAttribute Is Nothing) Or (_PropertyDescriptor.CanResetValue(_Form)) Then
            If _PropertyDescriptor.GetType().GetMethod("ResetValue", BindingFlags.Public Or BindingFlags.Instance) IsNot Nothing Then
                If _PropertyDescriptor.GetValue(_Form) IsNot Nothing Then
                    _PropertyDescriptor.ResetValue(_Form)
                End If
            End If
        End If
    Next
Next
于 2018-05-27T23:05:07.197 回答