ItemsSource for XamDockManager Elements
Varias personas han preguntado acerca de enlazar el ItemsSource de un TabGroupPane a su colección. Esto no es compatible con TabGroupPane, así que pensé en explicar por qué y proporcionar un enfoque alternativo.
Varias personas han preguntado acerca de enlazar el ItemsSource de un TabGroupPane a su colección. Esto no es compatible con TabGroupPane, así que pensé en explicar por qué y proporcionar un enfoque alternativo.
Si desea enlazar DocumentContentHost o incluso un SplitPane específico a una colección, debe seguir leyendo, ya que esta solución también lo permitirá.
TabGroupPane es un ItemsControl derivado y la propiedad ItemsSource que se ve en TabGroupPane es la de la clase base ItemsControl. ItemsControl está realmente diseñado para que los contenedores que se creen para los elementos de ItemsSource se hospeden dentro de ese ItemsControl, específicamente hospedado por el Panel indicado por la propiedad ItemsPanel. Por lo tanto, los elementos se insertan automáticamente en los elementos secundarios de ItemsPanel a medida que los elementos se agregan a la colección o, en el caso de un VirtualizingPanel, el panel tiene control sobre cuándo y qué contenedores se hidratan. Además, una vez que se establece el ItemsSource, no es posible cambiar directamente su colección Items: si lo hace, se producirá una excepción mediante el ItemCollection.
Si piensa en TabGroupPane, debe ser capaz de manipular los elementos que contiene, es decir, su colección Items. Esto puede suceder por varias razones. Por ejemplo, si el usuario final ancla o desancla un panel, arrastra un panel dentro o fuera del grupo, cambia el estado acoplado o flotante de uno de los elementos secundarios, etc. Dado que eso no sería posible si los elementos del control fueran proporcionados por su ItemsSource (ya que la colección Items no sería modificable), el control no puede admitir el enlace de su colección Items a través de ItemsSource.
Por lo tanto, ¿cómo se puede proporcionar compatibilidad con esto sin usar la propiedad ItemsSource? Si lo piensas, lo que necesitamos es algo análogo a ItemContainerGenerator. Se trata de una clase utilizada por ItemsControl y su ItemsPanel asociado para generar contenedores o elementos para elementos que no son del tipo deseado. Por lo tanto, para ListBox, se generan instancias de ListBoxItem para elementos que no son de ese tipo. Desafortunadamente, ItemContainerGenerator no se puede crear públicamente.
Por lo tanto, el enfoque que decidí adoptar fue crear mi propia clase de tipo ItemContainerGenerator denominada ContainerFactoryBase a la que se le podría dar una colección de origen y que mantendría una colección asociada de contenedores. En función del contenido de la colección, y a medida que la colección generaba notificaciones de cambio, invocaría métodos similares a los de ItemsControl en sí mismo que las clases derivadas podrían usar para crear el contenedor adecuado (por ejemplo, IsItemItsOwnContainer y GetContainerForItem) y asociar ese contenedor con el elemento (por ejemplo, ApplyItemContainerStyle y PrepareContainerForItem). Invocaría métodos a medida que se agregaran, quitaran o movieran los elementos de la colección de origen para que la clase derivada pudiera realizar la acción adecuada con el contenedor asociado.
A continuación, creé una clase derivada denominada ContentPaneFactory que crea instancias de ContentPane como contenedor para cada elemento y lo agrega al destino asociado. La clase expone varias propiedades de ruta de acceso que se pueden usar para enlazar las propiedades de ContentPane a las propiedades del elemento de datos, incluidas las propiedades Header, Content y TabHeader. Para cualquier otra propiedad, puede proporcionar un estilo para ContentPane mediante la propiedad ContainerStyle o puede usar la colección ItemBindings. Por último, también genero un evento adjunto (InitializeContentPane) cuando se crea un ContentPane para que pueda realizar cualquier inicialización mediante programación que sea necesaria.
Para que esto sea más fácil de usar, creé una propiedad adjunta que se usaría para asociar la fábrica con un destino determinado. Por lo tanto, establecería la propiedad ContentPaneFactory.PaneFactory en una instancia de ContentPaneFactory en TabGroupPane, SplitPane o DocumentContentHost y ese es el elemento de destino al que se agregan las nuevas instancias de ContentPane.
<igDock:DocumentContentHost >
<igExtensions:ContentPaneFactory.PaneFactory>
<!-- Binds to the Documents property of the DataContext. -->
<igExtensions:ContentPaneFactory
ItemsSource="{Binding Documents}"
HeaderPath="Name"
ContentPath="." />
</igExtensions:ContentPaneFactory.PaneFactory>
</igDock:DocumentContentHost>
Puedes obtener la muestra aquí.