Dynamic updating of Treeview Nodes

5 posts, 0 answers
  1. Donovan Bell
    Donovan Bell avatar
    29 posts
    Member since:
    Jul 2005

    Posted 07 Mar 2011 Link to this post

    Hi,

    I'm looking for advice on achieving dynamic updating of treeview nodes...

    The purpose of the RadTreeview in my project is to display computer objects (Computer name, and corresponding Icon (imagekey)).

    I have a method that executes on a different thread that applies the necassary changes to the treeview, i.e. if a computer status changes (is not reachable, etc) - it updates the necassary node's imageKey with the appropriate image.

    However, the changes to the node only appear if I expand or contract a parent node, or add /delete a node, etc.
    What is the best way to achieve a dynamic update without user intevention or reloading the tree?
  2. Emanuel Varga
    Emanuel Varga avatar
    1336 posts
    Member since:
    May 2010

    Posted 08 Mar 2011 Link to this post

    Hello Donovan,

    Just wrap your change statements in
    radTreeView1.BeginUpdate();
    // perform changes here
    radTreeView1.EndUpdate();

    Hope this helps, if you have any other questions or comments, please let me know,

    Best Regards,
    Emanuel Varga
    Telerik WinForms MVP
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Donovan Bell
    Donovan Bell avatar
    29 posts
    Member since:
    Jul 2005

    Posted 08 Mar 2011 Link to this post

    Thanks, but get a "Bounds cannot be changed while locked." exception when EndUpdate() method is called.

    Any Ideas?
  5. Emanuel Varga
    Emanuel Varga avatar
    1336 posts
    Member since:
    May 2010

    Posted 08 Mar 2011 Link to this post

    Hello again Donovan,

    I don't know exactly what you are doing there but please take a look at the following example:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Linq;
    using System.Threading;
    using System.Windows.Forms;
    using Telerik.WinControls.Commands;
    using Telerik.WinControls.UI;
     
    public partial class Form1 : Form
    {
        private RadTreeView radTreeView1;
        private List<TestObject> collection;
        private BackgroundWorker backgroundWorker;
     
        public Form1()
        {
            InitializeComponent();
            collection = new List<TestObject>();
            this.Size = new Size(400, 300);
            this.Controls.Add(radTreeView1 = new RadTreeView());
            radTreeView1.Dock = DockStyle.Fill;
            radTreeView1.ParentIDMember = "ParentId";
            radTreeView1.ValueMember = "Id";
            radTreeView1.DisplayMember = "Text";
     
            collection.Add(new TestObject { Id = 1, ParentId = 0, Text = "Parent1" });
            collection.Add(new TestObject { Id = 2, ParentId = 0, Text = "Parent2" });
            collection.Add(new TestObject { Id = 3, ParentId = 0, Text = "Parent3" });
            collection.Add(new TestObject { Id = 4, ParentId = 1, Text = "Child1" });
            collection.Add(new TestObject { Id = 5, ParentId = 1, Text = "Child2" });
            collection.Add(new TestObject { Id = 6, ParentId = 1, Text = "Child3" });
            collection.Add(new TestObject { Id = 7, ParentId = 2, Text = "Child4" });
            collection.Add(new TestObject { Id = 8, ParentId = 3, Text = "Child4" });
            collection.Add(new TestObject { Id = 9, ParentId = 3, Text = "Child5" });
            radTreeView1.DataSource = collection;
     
            var button = new RadToggleButton();
            button.Dock = DockStyle.Bottom;
            button.Text = "Start / Stop updates";
            button.ToggleStateChanged += new StateChangedEventHandler(button_ToggleStateChanged);
            this.Controls.Add(button);
     
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.WorkerSupportsCancellation = true;
        }
     
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            radTreeView1.ExpandAll();
        }
     
        void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var listItem = e.UserState as TestObject;
            if (listItem == null)
            {
                return;
            }
     
            UpdateTreeNode(listItem);
        }
     
        private void UpdateTreeNode(TestObject listItem)
        {
            radTreeView1.BeginUpdate();
            var text = listItem.Text;
            RadTreeNode node = null;
            FindByTextCommand cmd = new FindByTextCommand();
            List<object> result = RadTreeView.ExecuteBatchCommand(this.radTreeView1.Nodes, -1, cmd, text);
            if (result != null)
            {
                node = result.FirstOrDefault() as RadTreeNode;
            }
     
            if (text.Contains("Parent"))
            {
                var num = 0;
                var numText = text.Replace("Parent", string.Empty);
                int.TryParse(numText, out num);
                ++num;
                text = "Parent" + num.ToString();
            }
            else
            {
                var num = 0;
                var numText = text.Replace("Child", string.Empty);
                int.TryParse(numText, out num);
                ++num;
                text = "Child" + num.ToString();
            }
     
            if (node != null)
            {
                node.Text = text;
            }
     
            radTreeView1.EndUpdate();
        }
     
        void button_ToggleStateChanged(object sender, StateChangedEventArgs args)
        {
            if (backgroundWorker.IsBusy)
            {
                backgroundWorker.CancelAsync();
            }
            else
            {
                backgroundWorker.RunWorkerAsync();
            }
        }
     
        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            while (!backgroundWorker.CancellationPending)
            {
                var num = new Random(DateTime.Now.Millisecond).Next(0, collection.Count - 1);
                backgroundWorker.ReportProgress(0, collection[num]);
                Thread.Sleep(100 + DateTime.Now.Millisecond / 100 + num);
            }
        }
    }
     
    public class TestObject
    {
        private int id;
     
        public int Id
        {
            get { return id; }
            set { id = value; }
        }
     
        private int parentId;
     
        public int ParentId
        {
            get { return parentId; }
            set { parentId = value; }
        }
     
        private string text;
     
        public string Text
        {
            get { return text; }
            set
            {
                text = value;
            }
        }
    }

    This should help you achieve dynamic updates,
    Second, you should keep an eye out for the new and improved tree view that is scheduled for release sometime in the middle of march.

    Hope this helps, if you have any other questions or comments, please let me know,

    Best Regards,
    Emanuel Varga
    Telerik WinForms MVP
  6. Donovan Bell
    Donovan Bell avatar
    29 posts
    Member since:
    Jul 2005

    Posted 08 Mar 2011 Link to this post

    Thanks! May need to change my model slightly - thanks for the help!
Back to Top
UI for WinForms is Visual Studio 2017 Ready