Vb.net 为PropertyGrid-.NET更改多个属性中的一个属性-
如何仅重写控件的一个EditValue函数,同时保持该控件的所有其他属性可用?当我将单个控件指定给PropertyGrid的SelectedObject属性时,我将获得该控件的所有属性。为了覆盖一个属性,我想创建一个属性包装类,它将像以前一样显示所有控件,包括自定义EditValue函数。但是我发现我必须在包装器类中定义所有属性,否则我只能通过自定义EditValue函数查看属性。这似乎很不切实际,一定有更简单的办法。 我需要这样做,因为我想捕获用户可以指定的背景图像的文件名。 捕获名称的代码运行良好,这里是一个很好的度量:Vb.net 为PropertyGrid-.NET更改多个属性中的一个属性-,vb.net,propertygrid,uitypeeditor,Vb.net,Propertygrid,Uitypeeditor,如何仅重写控件的一个EditValue函数,同时保持该控件的所有其他属性可用?当我将单个控件指定给PropertyGrid的SelectedObject属性时,我将获得该控件的所有属性。为了覆盖一个属性,我想创建一个属性包装类,它将像以前一样显示所有控件,包括自定义EditValue函数。但是我发现我必须在包装器类中定义所有属性,否则我只能通过自定义EditValue函数查看属性。这似乎很不切实际,一定有更简单的办法。 我需要这样做,因为我想捕获用户可以指定的背景图像的文件名。 捕获名称的代码运
Friend Class CatchFileName : Inherits UITypeEditor
Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function
Public Overrides Function EditValue(context As ITypeDescriptorContext,
provider As IServiceProvider, value As Object) As Object
Dim ofd As New OpenFileDialog() With {.Filter = "Image Files|*.bmp;*.jpg;*.jpeg,*.gif;*.png;*.ewf;*.wmf;*.ico"}
If (ofd.ShowDialog() = DialogResult.OK) Then
DirectCast(context.Instance, FormPropertiesWrapper)._BackgroundImageName =
Path.GetFileName(ofd.FileName) ' Strip path
Return Image.FromFile(ofd.FileName)
End If
Return MyBase.EditValue(context, provider, value)
End Function
End Class
<Description("Defines a form's background image."), Category("Display")>
<Editor(GetType(CatchFileName), GetType(System.Drawing.Design.UITypeEditor))>
Public Property BackgroundImage() As Image
Get
Return _Form.BackgroundImage
End Get
Set(ByVal Value As Image)
_Form.BackgroundImage = Value
End Set
End Property
Friend类CatchFileName:继承UITypeEditor
公共重写函数GetEditStyle(作为ITypeDescriptorContext的上下文)作为UITypeEditorEditStyle
返回UITypeEditorEditStyle.Modal
端函数
公共重写函数EditValue(上下文为ITypeDescriptorContext,
提供程序作为IServiceProvider,值作为对象)作为对象
使用{.Filter=“Image Files |*.bmp;*.jpg;*.jpeg,*.gif;*.png;*.ewf;*.wmf;*.ico”}将ofd作为新的OpenFileDialog()进行调整
如果(ofd.ShowDialog()=DialogResult.OK),则
DirectCast(context.Instance,FormPropertiesWrapper)。\u BackgroundImageName=
Path.GetFileName(ofd.FileName)'条带路径
返回Image.FromFile(ofd.FileName)
如果结束
返回MyBase.EditValue(上下文、提供程序、值)
端函数
末级
公共属性BackgroundImage()作为图像
得到
返回_Form.BackgroundImage
结束
设置(ByVal值作为图像)
_Form.BackgroundImage=值
端集
端属性
_表单在包装类FormPropertiesWrapper中声明为表单。PropertyGrid使用组件的来确定网格中通过显示的内容。您可以创建一个从GetProperties方法派生并重写该方法的包装器类,以提供一个新的包装器类,其中包含指向您的
CatchFileName
类的
我修改了您的CatchFileName
类,使其能够处理名为IBackgroundImageName
的接口,该接口需要在包装控件中实现。此包装器将与实现BackgroundImageProxyWrapper.IBackgroundImageName
的任何控件一起使用。这样,图像名称存储在控件中而不是包装器中
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.IO
Friend Class BackgroundImageProxyWrapper : Inherits CustomTypeDescriptor
Private Sub New(source As IBackgroundImageName)
MyBase.New(TypeDescriptor.GetProvider(source).GetTypeDescriptor(source))
SourceControl = source
End Sub
Public Shared Function Wrap(Of T As {Control, IBackgroundImageName})(source As T) As BackgroundImageProxyWrapper
Return New BackgroundImageProxyWrapper(source)
End Function
Public ReadOnly Property SourceControl As IBackgroundImageName
Public Overrides Function GetProperties() As PropertyDescriptorCollection
Return GetProperties(Nothing)
End Function
Public Overrides Function GetProperties(attributes() As Attribute) As PropertyDescriptorCollection
Dim ret As PropertyDescriptorCollection
ret = New PropertyDescriptorCollection(New PropertyDescriptor() {}, False)
For Each pd As PropertyDescriptor In MyBase.GetProperties(attributes)
If pd.Name.Equals("BackgroundImage") Then
' substitute a PropertyDescriptor that includes the EditorAttribute
Dim attribs As New List(Of Attribute)(pd.Attributes.Count + 1)
Dim editorType As Type = GetType(EditorAttribute)
' 1st remove any previous editor attribute
For Each attrib As Attribute In pd.Attributes
If attrib.GetType IsNot editorType Then
attribs.Add(attrib)
End If
Next
attribs.Add(New EditorAttribute(GetType(CatchFileName), GetType(UITypeEditor)))
pd = TypeDescriptor.CreateProperty(pd.ComponentType, pd, attribs.ToArray())
End If
ret.Add(pd)
Next
Return ret
End Function
Private Class CatchFileName : Inherits UITypeEditor
Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function
Public Overrides Function EditValue(context As ITypeDescriptorContext,
provider As IServiceProvider, value As Object) As Object
Dim ofd As New OpenFileDialog() With {.Filter = "Image Files|*.bmp;*.jpg;*.jpeg,*.gif;*.png;*.ewf;*.wmf;*.ico"}
If (ofd.ShowDialog() = DialogResult.OK) Then
DirectCast(context.Instance, BackgroundImageProxyWrapper).SourceControl.BackgroundImageName =
Path.GetFileName(ofd.FileName) ' Strip path
Return Image.FromFile(ofd.FileName)
End If
Return MyBase.EditValue(context, provider, value)
End Function
End Class
Public Interface IBackgroundImageName
Property BackgroundImageName As String
End Interface
End Class
用法示例:
Public Class Form1
Implements BackgroundImageProxyWrapper.IBackgroundImageName
Private Property BackgroundImageName As String Implements BackgroundImageProxyWrapper.IBackgroundImageName.BackgroundImageName
Private Sub BtnSetForm_Click(sender As Object, e As EventArgs) Handles BtnSetForm.Click
PropertyGrid1.SelectedObject = BackgroundImageProxyWrapper.Wrap(Me)
End Sub
End Class
编辑:更通用的版本,可用于任何控件。文件名存储在控件的标记属性中
Friend Class BackgroundImageProxyWrapper : Inherits CustomTypeDescriptor
Public Sub New(source As Control)
MyBase.New(TypeDescriptor.GetProvider(source).GetTypeDescriptor(source))
SourceControl = source
End Sub
Public ReadOnly Property SourceControl As Control
Public Overrides Function GetProperties() As PropertyDescriptorCollection
Return GetProperties(Nothing)
End Function
Public Overrides Function GetProperties(attributes() As Attribute) As PropertyDescriptorCollection
Dim ret As PropertyDescriptorCollection
ret = New PropertyDescriptorCollection(New PropertyDescriptor() {}, False)
For Each pd As PropertyDescriptor In MyBase.GetProperties(attributes)
If pd.Name.Equals("BackgroundImage") Then
' substitute a PropertyDescriptor that includes the EditorAttribute
Dim attribs As New List(Of Attribute)(pd.Attributes.Count + 1)
Dim editorType As Type = GetType(EditorAttribute)
' 1st remove any previous editor attribute
For Each attrib As Attribute In pd.Attributes
If attrib.GetType IsNot editorType Then
attribs.Add(attrib)
End If
Next
attribs.Add(New EditorAttribute(GetType(CatchFileName), GetType(UITypeEditor)))
pd = TypeDescriptor.CreateProperty(pd.ComponentType, pd, attribs.ToArray())
End If
ret.Add(pd)
Next
Return ret
End Function
Private Class CatchFileName : Inherits UITypeEditor
Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function
Public Overrides Function EditValue(context As ITypeDescriptorContext,
provider As IServiceProvider, value As Object) As Object
Dim ofd As New OpenFileDialog() With {.Filter = "Image Files|*.bmp;*.jpg;*.jpeg,*.gif;*.png;*.ewf;*.wmf;*.ico"}
If (ofd.ShowDialog() = DialogResult.OK) Then
DirectCast(context.Instance, BackgroundImageProxyWrapper).SourceControl.Tag =
Path.GetFileName(ofd.FileName) ' Strip path
Return Image.FromFile(ofd.FileName)
End If
Return MyBase.EditValue(context, provider, value)
End Function
End Class
End Class
非常感谢你详细的回答。我时不时地学到很多东西。我将不得不消化这篇文章,你将展示一个例子,其中Implements语句被添加到一个类中。当标准控件(如Forms.Panel控件)的属性必须编辑时,该示例会是怎样的?@DuxburyDutch,此包装器不是为非用户派生控件设置的。如果这不能满足您的使用需求,那么返回/检索BackgroundImageName将需要以不同的方式实现。GetProperties方法的基本逻辑将保持不变。我只是觉得将值存储在包装器中不方便,但如果您想要这样做,请删除
IBackgroundImageName
接口用法,并将我的更改还原为CatchFileName
类,使其与您最初的更改相同。@DuxburyDutch,请参阅我的编辑。我添加了一个将文件名存储在控件的Tag属性中的版本。这将适用于任何控制。嗨@TnTinMn,再次感谢您的帮助。只是为了澄清一下,并不是我不想使用IBackgroundImageName接口,而是我认为除了使用包装类之外没有其他选择。。