为PropertyGrid更改多个属性中的一个-.NET-

问题描述

如何在保持该控件的所有其他属性可用的情况下仅覆盖控件的一个EditValue函数?当我将单个控件分配给PropertyGrid的Selectedobject属性时,我将获得控件的所有属性。为了覆盖一个属性,我想创建一个属性包装器类,该类将向我展示所有控件,包括自定义EditValue函数。但是我发现必须在包装类中定义所有属性,否则只能通过自定义EditValue函数查看该属性。这似乎非常不切实际,必须有一种更简单的方法。 我需要这样做,因为我想捕获用户可以指定的BackgroundImage的文件名。 捕获名称代码很好用,在这里是很好的措施:

const mockSendEmail = jest.fn(() => {
  return {
    promise() {
      return Promise.resolve('mock response');
    }
  };
});

jest.mock('aws-sdk',() => {
  return {
    SES: jest.fn(() => ({
      sendEmail: mockSendEmail
    })),config: {
      update: jest.fn()
    }
  };
});

_Form在包装类FormPropertiesWrapper中声明为Form

解决方法

PropertyGrid使用组件的TypeDescriptor来确定通过TypeDescriptor.GetProperties Method在网格中显示的内容。您可以创建一个派生自CustomTypeDescriptor Class的包装类,并重写GetProperties方法以提供一个新的PropertyDescriptor,其中包括指向您的CatchFileName类的EditorAttribute

我修改了您的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

编辑::适用于任何控件的更通用的版本。文件名存储在控件的Tag属性中。

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() {},BackgroundImageProxyWrapper).SourceControl.Tag =
           Path.GetFileName(ofd.FileName) ' Strip path
        Return Image.FromFile(ofd.FileName)
      End If
      Return MyBase.EditValue(context,value)
    End Function
  End Class
End Class