Soporta el editor en tiempo de diseño para la recolección de los controles
-
21-09-2019 - |
Pregunta
Me gustaría añadir una propiedad que representa una colección de controles a un componente y un editor de la colección con la que puedo seleccionar fácilmente los controles que pertenecen a la colección. VS hace casi lo que quiero de forma automática con el siguiente código:
Private _controls As New List(Of Control)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property SelectedControls() As List(Of Control)
Get
Return _controls
End Get
End Property
Me da la CollectionEditor por defecto, puede añadir y eliminar los controles, y la colección es de serie.
El problema es que no quiero añadir nuevos controles, quiero seleccionar varios controles de los otros controles disponibles en el formulario. ¿Hay alguna forma fácil / estándar de hacer esto, o voy a tener que escribir mi propio editor de la colección y ejecutar a través de la colección de controles?
A pesar de que hay un montón de material sobre editores de la colección (UITypeEditors) y otros temas en tiempo de diseño, no he podido encontrar ningún enlace que demuestran este comportamiento exacto, por lo que cualquier ayuda se agradece.
Solución
Aceptar, por lo que en la media hora que he tenido el almuerzo y escrito el editor de mí mismo. No fue un gran esfuerzo. Yo estaría encantado de compartir, si ayuda.
Editar: Solución Resumen
escribí un editor (ver captura de pantalla), que recurrentemente se enumeran todos los controles que se encuentran en el formulario en una vista de árbol. Si los controles tienen sus propiedades de texto o imagen set se muestra el texto / imagen. El usuario puede seleccionar varios controles con casillas de verificación e incluso filtrar la lista para sólo los controles de visualización de ciertos tipos.
(Debo admitir, sin embargo, que desde este editor sólo estaba destinado a uso interno, no se molestan en comprobar la propiedad de imagen de forma genérica, que se encarga solamente de un par de tipos de control conocidos.)
El código en la forma editor es realmente sólo para la interfaz de usuario, responsable de llenar el árbol, el establecimiento de los controles en la lista de controles preseleccionados y devolver la lista de controles seleccionados cuando el usuario cierra el formulario con OK.
A continuación, tenemos una clase que implementa UITypeEditor, que llamé FormControlSelectionEditor. Esta clase se asigna a las propiedades que queremos usar el editor para usar el atributo [Editor]. No hace mucho más que crear una nueva instancia del formulario cuando sea necesario y mostrarlo como un cuadro de diálogo modal.
Luego están los propios propiedades, que son de tipo System.Collections.ObjectModel.ObservableCollection (Of Control). Elegí ObservableCollection porque necesito para reaccionar a cambios en las listas en tiempo de ejecución, así, pero otras listas haría igual de bien con una mínima adaptación.
Una cosa que descubrí es que tuve que escribir mis propiedades y editor de tal manera que ellos usan copias de las listas de controles. En otras palabras, el código UITypeEditor hace una copia de la lista almacenada en la propiedad y la pasa a la forma editor (para ajustar los controles cuando se abre el formulario), y cuando se cierra el formulario, I Borrar lista el respaldo de la propiedad y copiar cada control en la lista devuelta desde el editor. Me encontré con que de otra manera he tenido problemas con la serialización en el archivo .designer. No creemos que tiene que ser así; Creo que es más probable un error de mi parte.
Código para una propiedad típica:
Private WithEvents _insertButtons As New System.Collections.ObjectModel.ObservableCollection(Of Control)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
<Editor(GetType(Design.FormControlSelectionEditor), GetType(UITypeEditor))> _
Public Property InsertButtons() As System.Collections.ObjectModel.ObservableCollection(Of Control)
Get
Return _insertButtons
End Get
Set(ByVal value As System.Collections.ObjectModel.ObservableCollection(Of Control))
If value Is Nothing Then
RemoveInsertButtonEventHandlers(_insertButtons)
_insertButtons.Clear()
Else
' Copy the list items passed in into the internal list
For i As Integer = _insertButtons.Count - 1 To 0 Step -1
If Not value.Contains(_insertButtons.Item(i)) Then _insertButtons.RemoveAt(i)
Next
For Each ctl As Control In value
If Not _insertButtons.Contains(ctl) Then _insertButtons.Add(ctl)
Next
End If
End Set
End Property
Private Function ShouldSerializeInsertButtons() As Boolean
Return _insertButtons.Count > 0
End Function
Private Sub ResetInsertButtons()
InsertButtons = Nothing
End Sub
He puesto el editor en un archivo zip; descargarlo aquí .
Como he mencionado antes, esto era sólo una solución rápida y sucia destinada a uso interno. De todos modos, le agradecería cualquier sugerencia de mejora.