【问题标题】:PropertyGrid Not Updating List of StringPropertyGrid 不更新字符串列表
【发布时间】:2015-11-07 12:15:06
【问题描述】:

PropertyGrid 有点麻烦。

我已将所选对象设置为包含各种属性的类,其中 90% 可以正常工作,但对于属性为 List(Of String) 的任何地方,它似乎都不会调用属性的 Set 部分。

我的课如下(缩短版):

Public Class VideosProperties
    Public Property EpisodeColorOdd As Color
        Get
            Return Videos_EpisodeColorOdd
        End Get
        Set(value As Color)
            Videos_EpisodeColorOdd = value
        End Set
    End Property

    <Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    "System.Drawing.Design.UITypeEditor,System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")>
    Public Property Extensions As List(Of String)
        Get
            Return Videos_Extensions
        End Get
        Set(value As List(Of String))
            Videos_Extensions = value
        End Set
    End Property
End Class

我已使用以下代码将SelectedObject 设置为此类:

Dim _Properties As Object

_Properties = New VideosProperties

PropertyGrid1.SelectedObject = _Properties

我已使用以下代码初始化列表:

Extensions = New List(Of String)

当我运行我的代码时,PropertyGrid 会显示 EpisodeColorOdd 属性,这可以正常工作,但 Extensions 属性不能。

当您使用PropertyGrid 编辑扩展属性时,它不会调用属性的Set(value as List(Of String)) 部分。

我环顾四周,似乎找不到解决方案(我可能还不够努力)。

谁能帮忙?

编辑

Plutonix - 您的代码不起作用。我已经复制并粘贴到一个新项目中,但出现错误。
我收到一个错误

<Editor("System.Windows.Forms...etc")> 

告诉我“类型 'Editor' 未定义”,所以我导入了“System.ComponentModel”,现在得到 错误提示“重载解析失败,因为没有可访问的‘新’接受此数量的参数。”在同一点。

如果我删除了那个部分,它就不能正常工作。

我运行代码,打开表单,单击 Foods 属性并打开一个编辑器,单击添加并收到错误“未找到类型 'System.String' 的构造函数”。我以前吃过的, 我用

修复了
<Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor,System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")> 

而不是

<Editor("System.Windows.Forms...etc")>

现在,当我单击该属性时,它会打开一个不同的编辑器,并且实际上并没有访问该属性的 Set 部分。所以,我又回到了原点。

【问题讨论】:

  • a) "...etc" 显然是长编辑器名称的简写,抱歉。 b) 没有关于何时何地实例化扩展列表的上下文。 c) doesn't actually access the Set part of the property 它永远不会也不应该。重新阅读答案。集合编辑器编辑集合中的项目,不是集合对象
  • 我想我可能误解了你的帖子。我刚刚检查过,它会更新代码的Get 部分中的列表。这是一个问题的原因是因为在所有其他属性的Set 部分,我正在调用一些代码来更新我的注册表。由于它没有使用Set,它没有更新,它基本上没有保存我的设置。我现在已经将此代码添加到Get 区域并且它工作正常。感谢您的帮助,Plutonix,非常感谢。 :-)
  • This link 解释了集合编辑器的工作原理。如果您必须限定/处理每个项目,请使用生成事件的列表或编写集合类。当编辑器调用.Add.AddRange 方法时,您可以让代码验证项目或其他任何内容。

标签: .net vb.net properties propertygrid


【解决方案1】:

我不能确定,但​​从显示的代码来看,您没有初始化集合。 PropertyGridStringCollectionEditor 都用于编辑现有 属性值。通过不初始化 List(它本身就是一个对象),该属性容器不存在,并且它们都不会为您创建它。

您的代码显示了 getter/setter 样板,但没有显示支持字段。

另外,由于VideosProperties 是一个类型,你应该使用它来将你的变量声明为那个类型而不是As Object。通过这样做,您将 var 转换为可能的最低形式;您的属性只能通过需要关闭Option Strict 的后期绑定获得。

Public Class Animal
    ' auto implement props available since VS2010:
    Public Property Name As String
    Public Property Species As String
    Public Property Weight As Double
    Public Property Coloring As Color

    ' backing field for the List:
    Private mFoods As List(Of String)

    ' this of course would be the same as your code...
    ' no need to repeat
    <Editor("System.Windows.Forms...etc")>
    Public Property Foods As List(Of String)
        Get
            Return mFoods
        End Get
        Set(value As List(Of String))
            ' see notes
        End Set
    End Property

    Public Sub New(n As String, s As String)
        Name = n
        Species = s
        ' initialize the List instance:
        mFoods = New List(Of String)
    End Sub
End Class

关键是在构造函数 (Sub New) 中创建列表实例来保存食物、视频扩展或其他内容。使用它:

' class/form level variable declared as Animal NOT Object
Private A As Animal
...
A = New Animal("Ziggy", "Feline")
A.Weight = 12.4             ' not possible if A is As Object

pGrid.SelectedObject = A

编辑后,A.Foods 将包含通过StringCollectionEditor 输入的任何内容。如果A 被声明为As Object,则设置Weight 的代码行将阻止代码编译(启用Option Strict)。这是因为System.Object 没有Weight 属性。 A As Animal 允许编译器查看和使用定义的属性。我怀疑你没有使用Option Strict

如果当您将对象发送到PropertyGrid 时,您的对象具有有效的List 实例并且指定了有效的编辑器,您将看到:

PropGrid 将显示“Collection”,表示它知道它是什么,“...”表示 PropGrid 具有与其关联的有效编辑器。证明它保留了收藏:

lbFoods.Items.AddRange(A.Foods.ToArray)
' results in:


请注意,我在 Foods 的设置器中没有任何内容,但它可以工作。集合编辑器通常不会通过 setter en masse 将集合项传回。相反,他们使用集合的Add 和/或AddRange 方法。

所以,我可以省略设置器,它也可以防止某些代码将List 设置回Nothing。当然,代码可以将字符串项目更改为其他内容或重新排序它们,这也可能是坏的。

为避免这种情况,您可能需要使用实现List(of T)Collection(Of T) 的集合类。通过这种方式,您的代码可以提供对项目的访问、限制可以执行的操作,甚至验证添加的项目。

有关更多提示和信息,请参阅Guidelines for Collections

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 2016-04-06
    • 2011-03-08
    • 2021-09-14
    • 2010-09-12
    • 2017-10-01
    • 2023-04-05
    • 1970-01-01
    • 2013-09-05
    相关资源
    最近更新 更多