TOC

This article has been localized into Portuguese by the community.

O controle TreeView:

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.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!