我在 C# 中为 WinForms 制作了一个自定义控件。它的属性之一是将在某个时候播放的音频流。有没有办法告诉 VS 这个属性应该从具有属性或类似属性的资源清单(特别是音频资源)中选择?
被注释的属性是一个音频流。
这就是它在 WinForms 设计器中的显示方式。
这是您单击编辑 [...] 按钮时得到的结果。我希望将其替换为 [audio] 资源选择器。
我在 C# 中为 WinForms 制作了一个自定义控件。它的属性之一是将在某个时候播放的音频流。有没有办法告诉 VS 这个属性应该从具有属性或类似属性的资源清单(特别是音频资源)中选择?
被注释的属性是一个音频流。
这就是它在 WinForms 设计器中的显示方式。
这是您单击编辑 [...] 按钮时得到的结果。我希望将其替换为 [audio] 资源选择器。
您正在寻找的是:
[Editor(typeof(MyAudioEditor), typeof(UITypeEditor)]
此属性允许您指定在属性网格中显示该属性时要使用的特定编辑器。
然后,您可以从基本类型派生和创建新编辑器。基类型必须是或必须派生自 System.Drawing.Design.UITypeEditor。
在大多数情况下,当调用编辑器时,您会弹出一个您选择的表单,并将其返回值绑定到您的属性。
UITypeEditor 有 4 个虚拟方法和一个虚拟属性,可让您在有人与您的属性交互或在网格中绘制您的属性时更改所有行为。
我在下面发布了一个代码,显示了我自己会如何做。
只是一些观察:
AudioName
将在设计器中设置的 String 属性。此属性引用程序集中的资源名称。Audio
然后将从所选资源名称中检索您感兴趣的 Stream 类型的(只读)属性。正如 Marc-André Jutras 在他的回答中指出的那样,您需要自己编写代码UITypeEditor
或TypeConverter
从程序集中检索音频资源。在这种情况下,我选择实现一个自定义TypeConverter
.
Public Class Form1
<System.ComponentModel.TypeConverter(GetType(AudioConverter)), System.ComponentModel.DefaultValue("(none)")>
Public Property AudioName As String
<System.ComponentModel.Browsable(False)> 'This will make the property not appear in the designer
Public ReadOnly Property Audio As Stream
Get
If String.IsNullOrWhiteSpace(AudioName) OrElse
AudioName = "(none)" Then
Return Nothing
End If
Try
Return My.Resources.ResourceManager.GetStream(AudioName)
Catch ex As Exception
Return Nothing
End Try
End Get
End Property
End Class
Public Class AudioConverter
Inherits System.ComponentModel.TypeConverter
Public Overrides Function GetStandardValuesSupported(context As System.ComponentModel.ITypeDescriptorContext) As Boolean
Return True
End Function
' Set the property to be informed only from predefined (standard) values
Public Overrides Function GetStandardValuesExclusive(context As System.ComponentModel.ITypeDescriptorContext) As Boolean
Return True
End Function
' Get possible values that will be inserted in the drop-down list
Public Overrides Function GetStandardValues(context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
Dim returnList As New System.Collections.Generic.List(Of String)
returnList.Add("(none)")
For Each resItem As System.Collections.DictionaryEntry In My.Resources.ResourceManager.GetResourceSet(System.Globalization.CultureInfo.InvariantCulture, True, False)
Dim resourceEntry As String = resItem.Key
If TypeOf resourceEntry Is String Then
returnList.Add(resourceEntry)
End If
Next
Return New System.ComponentModel.TypeConverter.StandardValuesCollection(returnList)
End Function
End Class