This article has been localized into Portuguese by the community.
Lazy loading em itens do TreeView
O processo usual ao usar o TreeView é vincular a uma coleção de itens ou adicionar manualmente cada nível ao mesmo tempo. No entanto, em algumas situações, você deseja atrasar o carregamento de itens filhos de nós até que eles sejam realmente necessários. Isso é especialmente útil se você tiver uma árvore muito profunda, com muitos níveis e nós filhos e um ótimo exemplo disso, é a estrutura de pastas do seu computador Windows.
Cada unidade no seu computador Windows tem um intervalo de pastas filho, e cada uma dessas pastas filho tem pastas filho abaixo delas e assim por diante. Looping através de cada unidade e cada unidade de pastas filho pode se tornar extremamente demorada e seu TreeView logo consistiria em um monte de nós, com uma alta porcentagem deles nunca será necessário. Esta é a tarefa perfeita para um TreeView carregado com preguiça, onde as pastas filhas são carregadas apenas sob demanda.
Para conseguir isso, simplesmente adicionamos uma pasta fictícia a cada unidade ou pasta filha e, quando o usuário a expande, removemos a pasta fictícia e a substituímos pelos valores reais. É assim que a nossa aplicação parece quando é iniciada - nessa altura, apenas obtivemos uma lista de unidades disponíveis no computador:
Agora você pode começar a expandir os nós e o aplicativo carregará automaticamente as subpastas. Se uma pasta estiver vazia, ela será mostrada como vazia quando você tentar expandi-la, como pode ser visto na próxima captura de tela:
Então, como isso é feito? Vamos dar uma olhada no código:
<Window x:Class="WpfTutorialSamples.TreeView_control.LazyLoadingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="LazyLoadingSample" Height="300" Width="300">
<Grid>
<TreeView Name="trvStructure" TreeViewItem.Expanded="TreeViewItem_Expanded" Margin="10" />
</Grid>
</Window>
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
namespace WpfTutorialSamples.TreeView_control
{
public partial class LazyLoadingSample : Window
{
public LazyLoadingSample()
{
InitializeComponent();
DriveInfo[] drives = DriveInfo.GetDrives();
foreach(DriveInfo driveInfo in drives)
trvStructure.Items.Add(CreateTreeItem(driveInfo));
}
public void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
{
TreeViewItem item = e.Source as TreeViewItem;
if((item.Items.Count == 1) && (item.Items[0] is string))
{
item.Items.Clear();
DirectoryInfo expandedDir = null;
if(item.Tag is DriveInfo)
expandedDir = (item.Tag as DriveInfo).RootDirectory;
if(item.Tag is DirectoryInfo)
expandedDir = (item.Tag as DirectoryInfo);
try
{
foreach(DirectoryInfo subDir in expandedDir.GetDirectories())
item.Items.Add(CreateTreeItem(subDir));
}
catch { }
}
}
private TreeViewItem CreateTreeItem(object o)
{
TreeViewItem item = new TreeViewItem();
item.Header = o.ToString();
item.Tag = o;
item.Items.Add("Loading...");
return item;
}
}
}
O XAML é muito simples e apenas um detalhe interessante está presente: A maneira como nos inscrevemos no evento expandido de TreeViewItem. Note que este é realmente o TreeViewItem e não o próprio TreeView, mas como o evento se forma, podemos capturá-lo em um só lugar para o TreeView inteiro, em vez de assiná-lo para cada item que adicionamos à árvore. . Esse evento é chamado toda vez que um item é expandido, o que precisamos estar cientes para carregar seus itens filhos sob demanda.
Em Code-behind , começamos adicionando cada unidade encontrada no computador ao controle TreeView. Atribuímos a instância DriveInfo à propriedade Tag, para depois recuperá-la. Observe que usamos um método personalizado para criar o TreeViewItem, chamado CreateTreeItem () , já que podemos usar exatamente o mesmo método quando quisermos adicionar dinamicamente uma pasta filha mais tarde. Observe neste método como adicionamos um item filho à coleção Items, na forma de uma string com o texto "Carregando ...".
Em seguida é o evento TreeViewItem_Expanded. Como já mencionado, este evento é gerado toda vez que um item TreeView é expandido, então a primeira coisa que fazemos é verificar se este item já foi carregado, verificando se os itens filhos consistem atualmente em apenas um item, que é uma string. - Nesse caso, encontramos o item filho "Carregando ...", o que significa que agora devemos carregar o conteúdo real e substituir o item de espaço reservado por ele.
Agora usamos a propriedade Tag de itens para obter uma referência à instância DriveInfo ou DirectoryInfo que o item atual representa e, em seguida, obtemos uma lista de diretórios filhos, que adicionamos para o item clicado, mais uma vez usando o método CreateTreeItem () . Observe que o loop em que adicionamos cada pasta filha está em um bloco try..catch - isso é importante, porque alguns caminhos podem não estar acessíveis, geralmente por motivos de segurança. Você pode pegar a exceção e usá-la para refletir isso na interface de uma maneira ou de outra.
Resumo
Assinando o evento Expanded, podemos criar facilmente um TreeView carregado com preguiça, que pode ser uma solução muito melhor do que a criada estaticamente em várias situações.