ItemsSource para elementos XamDockManager
Várias pessoas perguntaram sobre a associação do ItemsSource de um TabGroupPane à sua coleção. Isso não é suportado pelo TabGroupPane, então pensei em explicar o porquê e fornecer uma abordagem alternativa.
Várias pessoas perguntaram sobre a associação do ItemsSource de um TabGroupPane à sua coleção. Isso não é suportado pelo TabGroupPane, então pensei em explicar o porquê e fornecer uma abordagem alternativa.
Se você deseja associar o DocumentContentHost ou até mesmo um SplitPane específico a uma coleção, ainda deve continuar lendo, pois essa solução também permitirá isso.
O TabGroupPane é um ItemsControl derivado e a propriedade ItemsSource que você vê no TabGroupPane é a da classe ItemsControl base. O ItemsControl foi realmente projetado para que todos os contêineres criados para itens no ItemsSource sejam hospedados nesse ItemsControl – especificamente hospedados pelo Panel indicado pela propriedade ItemsPanel. Portanto, os itens são enviados automaticamente para os filhos do ItemsPanel à medida que os itens são adicionados à coleção ou, no caso de um VirtualizingPanel, o painel tem controle sobre quando/quais contêineres são hidratados. Além disso, depois de definir o ItemsSource, não é possível alterar diretamente sua coleção Items – uma exceção será lançada pelo ItemCollection se você fizer isso.
Se você pensar no TabGroupPane, ele precisa ser capaz de manipular os itens que ele contém – ou seja, sua coleção Items. Isso pode acontecer por vários motivos. Por exemplo, se o usuário final fixar/desafixar um painel, arrastar um painel para dentro ou para fora do grupo, alterar o estado encaixado/flutuante de um dos filhos, etc. Como isso não seria possível se os itens do controle fossem fornecidos por seu ItemsSource (já que a coleção Items não seria modificável), o controle não pode dar suporte à associação de sua coleção Items por meio do ItemsSource.
Então, como podemos fornecer suporte para isso sem usar a propriedade ItemsSource. Se você pensar sobre isso, o que precisamos é de algo análogo ao ItemContainerGenerator. Essa é uma classe usada pelo ItemsControl e seu ItemsPanel associado para gerar contêineres/elementos para itens que não são do tipo desejado. Portanto, para um ListBox, as instâncias de ListBoxItem são geradas para itens que não são desse tipo. Infelizmente, o ItemContainerGenerator não pode ser criado publicamente.
Portanto, a abordagem que decidi adotar foi criar minha própria classe do tipo ItemContainerGenerator chamada ContainerFactoryBase que poderia receber uma coleção de origem e manteria uma coleção associada de contêineres. Com base no conteúdo da coleção e à medida que a coleção gerava notificações de alteração, ela invocaria métodos semelhantes aos do ItemsControl em si mesmo que as classes derivadas poderiam usar para criar o contêiner apropriado (por exemplo, IsItemItsOwnContainer e GetContainerForItem) e associar esse contêiner ao item (por exemplo, ApplyItemContainerStyle e PrepareContainerForItem). Ele invocaria métodos à medida que os itens na coleção de origem fossem adicionados/removidos/movidos para que a classe derivada pudesse executar a ação apropriada com o contêiner associado.
Em seguida, criei uma classe derivada chamada ContentPaneFactory que cria instâncias de ContentPane como o contêiner para cada item e a adiciona ao destino associado. A classe expõe várias propriedades de caminho que podem ser usadas para associar propriedades do ContentPane às propriedades do item de dados, incluindo as propriedades Header, Content e TabHeader. Para quaisquer outras propriedades, você pode fornecer um Style para ContentPane usando a propriedade ContainerStyle ou pode usar a coleção ItemBindings. Por fim, também gero um evento anexado (InitializeContentPane) quando um ContentPane é criado para que você possa fazer qualquer inicialização programática que possa ser necessária.
Para facilitar o uso, criei uma propriedade anexada que seria usada para associar a fábrica a um determinado destino. Portanto, você definiria a propriedade ContentPaneFactory.PaneFactory como uma instância de ContentPaneFactory em um TabGroupPane, SplitPane ou DocumentContentHost e esse é o elemento de destino ao qual novas instâncias de ContentPane são adicionadas.
<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>
Você pode obter a amostra aqui.