Понеділок, 17 вересня 2007 р.

Lazy loading of TreeView nodes


Lazy load (або відкладене завантаження) - це завантаження деяких даних по необхідності їх використання. В даному випадку ми маєм деяке дерево даних відображене за допомогою .net компонента TreeView. Якшо дані, які потрібно відобразити за допомогою TreeView є досить об’ємними (тобто на деякому рівні дерева їх є досить велика кількість), то процес побудови дерева затягується у відповідності до збільшення кількості цих даних. Тому доцільно не завантажувати одразу всі дані для формування одразу всього дерева, а надавати їх по мірі необхідності (коли користувач розгорне ту чи іншу вітку). Для цього потрібно підписатись на event TreeView-а "BeforeExpand" і в ньому вже робити з віткою що розгортаєть все що завгодно. В нашому випадку потрібно дозавантажити дані які мають відобразитись під даною віткою. Нижче приведено клас з двома статичними функціями які по суті і роблять TreeView з відкладеним завантаженням віток. Метод SubscribeExpand реєструє вітку і відповідний їй метод який викличеться при розгортанні. А CheckExpandSubscribtion потрібно викликати якраз в підписці на BeforeExpand, тобто коли ми почнем розгортати вітку метод CheckExpandSubscribtion провірить чи існує для вітки що розгортаєтсья метод для відкладеного завантаження і якшо так то визиває його.

public class TreeViewUtils
{
public static void SubscribeExpand(TreeNode node, NodeExpand expandDelegate)
{
Hashtable expandSubscriptions = node.TreeView.Tag as Hashtable;
if(null == expandSubscriptions)
{
expandSubscriptions = new Hashtable();
node.TreeView.Tag = expandSubscriptions;
}
node.Nodes.Add("");
expandSubscriptions[node] = expandDelegate;
}
public static void CheckExpandSubscribtion(TreeNode node)
{
Hashtable expandSubscriptions = node.TreeView.Tag as Hashtable;
if(null != expandSubscriptions && null != expandSubscriptions[node])
{
NodeExpand expandDelegate = expandSubscriptions[node] as NodeExpand;
if(null != expandDelegate)
{
node.Nodes.Clear();
expandDelegate(node);
}
}
}
}

Приклад:

//конструктор
public Form1()
{
InitializeComponent();
//добавляєм вітку
TreeNode node = treeView1.Nodes.Add("test");
//реєструєм метод відкладеного завантаження для даної вітки
TreeViewUtils.SubscribeExpand(node,new NodeExpand(testExpand));
//підписка на BeforeExpand
treeView1.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.treeView1_BeforeExpand);
}
...
private void testExpand(TreeNode node)
{
TreeViewUtils.SubscribeExpand(node.Nodes.Add("hello world!"),new NodeExpand(testExpand));
}
...
private void treeView1_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
{
TreeViewUtils.CheckExpandSubscribtion(e.Node);
}


В цьому прикладі дерево буде мати вітку "test" при розгортанні якої дістанем підвітку "hello world!" при розгортанні якої дістанем підвітку "hello world!" і так далі до "скільки пам’яті хватить" :).
пс.
Дуже раджу при відображенні даних з БД коли ці дані достатньо об’ємні.

0 коментарів: