Expand LOD-item programmatically

8 posts, 0 answers
  1. Doxxer
    Doxxer avatar
    5 posts
    Member since:
    Nov 2011

    Posted 12 Nov 2011 Link to this post

    Hi,

    I'm using MVVM (no code-behind!) with the treeview and it's on Load on demand (call method on WCF side etc...)
    I would like to add search capability in TreeView, but no one of the child nodes doesn't know about his child nodes, so I need again async call WCF-method to find A WAY to proper item. It works.

    But, when user clicks on item expander, occurs event "LoadOnDemand" and it passed to ViewModel:
    <i:EventTrigger EventName="LoadOnDemand">
        <MVVMLightCommand:EventToCommand Command="{Binding LoadOnDemandCommand}" PassEventArgsToCommand="True" />
    </i:EventTrigger>

    But I have problem:
    How can I expand that Item programmatically? When i set "IsExpanded = true" nothing happens, there is just spinning arrow in me tree. And event doesnt occur.

    Note: when I set "IsExpanded = true" in CODE-BEHIND - everything works fine! Can I expand lod-item in ViewModel?

    Thank you and sorry for my english. I would appreciate a fast response.
  2. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 16 Nov 2011 Link to this post

    Hi Doxxer,

    I am not sure if I understand your scenario completely. I am not sure where you set the IsExpanded property in your view model?

    Basically if an item is expanded before its children collection is loaded, then the changed expanded state will trigger the load on demand logic - the command action in your case. However, if the item's children collection is already loaded, then changing the expanded state of the node won't trigger the LoadOnDemand logic.

    However, you say that it's not only that the load on demand logic isn't triggered, but the item isn't expanded at all. This is why I wanted to ask you to please make sure that the RadTreeViewItem IsExpanded property is bound in a TwoWay mode to your business property in the view model.

    If the IsExpaned property is bound in a TwoWay mode and changing the data property still doesn't affect the RadTreeViewItem, it would be best to send us a sample solution reproducing the issue so that we can examine your implementation and look for the cause of the issue.

    All the best,
    Tina Stancheva
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
  4. Doxxer
    Doxxer avatar
    5 posts
    Member since:
    Nov 2011

    Posted 17 Nov 2011 Link to this post

    Hi, Tina

    Ok, I'll try to describe the problem and my sample solution.
    First of all, important notes:
    • Realy project is much more difficult, classes have much more properties, but they don't need to present my problem.
    • In main project some of nodes have more than 3000 children, so I set IsVirtualized=true
    • In my main project, the nesting level is unknown, so I have to use recursive calls
    • Last note: In main project I create inherited class RadTreeViewEx (from RadTreeView), with 2 Dependency Properties (its for search ability), and I tried to call this.ExpandItemByPass(path), but event still doesn't occur.

    Ok. Lets describe my problem:
    1. On server side is WCF-service. It consists of two projects, the first is simple ClassLibrary, the second is service. ClassLibrary consists of one base class, and 4 inherited classes: Depart, Group, SGroup (subgroup) and Product.
      So, as you can see in the GetProductNomenclature() method, each depart contains of 5 groups, each group contains 5 subgroups. The subgroup will be loaded on demand.
      And in the method GetProductsFromSGroup(), each subgroup will contain 10 items - that method will be called when event LoadOnDemand occurs.
      An example of server-side code:
      namespace RCP.Server.Data
      {
          [DataContract]
          [KnownType("GetKnownTypes")]
          public class NomenclaturalUnit
          {
              public NomenclaturalUnit()
              {
                  Children = new List<NomenclaturalUnit>();
              }
       
              private static Type[] GetKnownTypes()
              {
                  return new[] {typeof (Depart), typeof (GGroup), typeof (SGroup), typeof (Product)};
              }
       
              [DataMember]
              public decimal ID { get; set; }
       
              [DataMember]
              public string Name { get; set; }
       
              [DataMember]
              public List<NomenclaturalUnit> Children { get; set; }
          }
           
          [DataContract]
          public class Depart : NomenclaturalUnit
          {
          }
       
          [DataContract]
          public class GGroup : NomenclaturalUnit
          {
          }
       
          [DataContract]
          public class SGroup : NomenclaturalUnit
          {
          }
       
          [DataContract]
          public class Product : NomenclaturalUnit
          {
               
          }
      }

      And for WCF Service:
      [ServiceContract]
      public interface IRCPMainService
      {
          [OperationContract]
          List<NomenclaturalUnit> GetProductNomenclature();
       
          [OperationContract]
          List<NomenclaturalUnit> GetProductsFromSGroup(int idSgroup);
      }
       
       
      public class RCPMainService : IRCPMainService
          {
              public List<NomenclaturalUnit> GetProductNomenclature()
              {
                  var departs = Enumerable.Range(0, 5).Select(i => new Depart {ID = i, Name = string.Format("Depart {0}", i)}).ToList();
                  foreach (var depart in departs)
                  {
                      var groups = Enumerable.Range(0, 5).Select(i => new GGroup {ID = i, Name = string.Format("Group {0}", i)}).ToList();
                      foreach (var gGroup in groups)
                      {
                          var sgroups = Enumerable.Range(0, 5).Select(i => new SGroup {ID = i, Name = string.Format("SGroup {0}", i)}).ToList();
                          gGroup.Children.AddRange(sgroups);
                      }
                      depart.Children.AddRange(groups);
                  }
                  return new List<NomenclaturalUnit>(departs);
              }
       
              public List<NomenclaturalUnit> GetProductsFromSGroup(int idSGroup)
              {
                  // Each subgroup has 10 products
                   
                  return new List<NomenclaturalUnit>(
                      Enumerable.Range(0, 10).Select(i => new Product
                                                              {
                                                                  ID = i,
                                                                  Name = string.Format("Product {0}", i)
                                                              }));
              }
          }
    2. On the client side we have a simple Silverlight application (RadControlsSilverlightApp). Then I add Service Reference, so I have MODEL, in proxy-namespace RadControlsSilverlightApp1.MainServiceReference (see screenshot_1)
      Then wrap our classes in UI-wrap-class, creating NomenclatureViewModel class. It class "represents" RadTreeViewItem. It contains a reference to NomenclaturalUnit (defined in WCF service, and, therefore in proxy-namespace), collection of child items of NomenclatureViewModel type and properties IsSelected, IsExpanded and IsLoadOnDemandEnabled. BTW, IsLoadOnDemandEnabled always False, except when NomenclaturalUnit is SGroup. (So, we have only 1 LOD-level - the third)
      public class NomenclatureViewModel : ViewModelBase
          {
              public NomenclaturalUnit NomenclaturalUnit { get; protected set; }
       
              public ObservableCollection<NomenclatureViewModel> Children { get; set; }
       
       
              public NomenclatureViewModel(NomenclaturalUnit nomenclaturalUnit)
              {
                  _isLoadOnDemandEnabled = false;
                  NomenclaturalUnit = nomenclaturalUnit;
                  Children = new ObservableCollection<NomenclatureViewModel>();
                  foreach (var nomenclatureViewModel in nomenclaturalUnit.Children.Select(child => new NomenclatureViewModel(child) { IsLoadOnDemandEnabled = child is SGroup }))
                  {
                      Children.Add(nomenclatureViewModel);
                  }
              }
               
              private bool _isLoadOnDemandEnabled;
              public virtual bool IsLoadOnDemandEnabled
              {
                  get { return _isLoadOnDemandEnabled; }
                  set
                  {
                      _isLoadOnDemandEnabled = value;
                      OnPropertyChanged("IsLoadOnDemandEnabled");
                  }
              }
       
              private bool _isSelected;
              public bool IsSelected
              {
                  get { return _isSelected; }
                  set
                  {
                      if (_isSelected != value)
                      {
                          _isSelected = value;
                          OnPropertyChanged("IsSelected");
                      }
                  }
              }
       
              private bool _isExpanded;
              public bool IsExpanded
              {
                  get { return _isExpanded; }
                  set
                  {
                      if (_isExpanded != value)
                      {
                          _isExpanded = value;
                          OnPropertyChanged("IsExpanded");
                      }
                  }
              }
          }
    3. Then I create ViewModel class, that will be an UI-wrap over the whole RadTreeView (its DataContext)
      public class ViewModel : ViewModelBase
          {
              public ViewModel()
              {
                  SetupCommands();
                  NomenclatureCollection = new ObservableCollection<NomenclatureViewModel>();
              }
       
              #region Presentation Properties
       
              public ObservableCollection<NomenclatureViewModel> NomenclatureCollection { get; set; }
       
              private bool _loadingOnDemand;
              public bool LoadingOnDemand
              {
                  get { return _loadingOnDemand; }
                  set
                  {
                      if (_loadingOnDemand != value)
                      {
                          _loadingOnDemand = value;
                          OnPropertyChanged("LoadingOnDemand");
                      }
                  }
              }
       
              #endregion
       
              #region Setup Commanding
       
              public ICommand LoadedCommand { get; set; }
              public ICommand LoadOnDemandCommand { get; set; }
              public ICommand SelectCommand { get; set; }
       
              private void SetupCommands()
              {
                  LoadedCommand = new DelegateCommand(o => Loaded());
                  LoadOnDemandCommand = new RelayCommand<RadRoutedEventArgs>(LoadOnDemand, args => true);
                  SelectCommand = new DelegateCommand(o => SelectItemInTree());
              }
       
              #endregion
       
              #region Event Handlers
       
              /// <summary>
              /// Метод вызывает при наступления события Loaded главного окна
              /// </summary>
              private void Loaded()
              {
                  var serviceClient = new RCPMainServiceClient();
                  serviceClient.GetProductNomenclatureCompleted +=
                      (sender, e) =>
                      {
                          foreach (var item in e.Result)
                          {
                              NomenclatureCollection.Add(new NomenclatureViewModel(item));
                          }
                      };
                  serviceClient.GetProductNomenclatureAsync();
       
              }
       
              /// <summary>
              /// Метод вызывается при наступлении события LoadOnDemand исходного RadTreeView (разворачивание узла)
              /// </summary>
              /// <param name="e">Параметры</param>
              private void LoadOnDemand(RadRoutedEventArgs e)
              {
                  var currentItem = e.OriginalSource as RadTreeViewItem;
                  if (currentItem != null)
                  {
                      var unitViewModel = currentItem.Item as NomenclatureViewModel;
                      if (unitViewModel != null && unitViewModel.NomenclaturalUnit is SGroup)
                      {
                          var sGroup = unitViewModel.NomenclaturalUnit as SGroup;
                          var serviceClient = new RCPMainServiceClient();
       
                          serviceClient.GetProductsFromSGroupCompleted +=
                              (s, args) =>
                              {
                                  foreach (var item in args.Result)
                                  {
                                      sGroup.Children.Add(item);
                                  }
                                  foreach (var nomenclatureViewModel in sGroup.Children.Select(child => new NomenclatureViewModel(child)))
                                  {
                                      unitViewModel.Children.Add(nomenclatureViewModel);
                                  }
                                  e.Handled = true;
                                  unitViewModel.IsLoadOnDemandEnabled = false;
                                  LoadingOnDemand = false;
       
                              };
                          LoadingOnDemand = true;
                          serviceClient.GetProductsFromSGroupAsync((int)sGroup.ID);
                      }
                  }
              }
       
              #endregion
       
              private void SelectItemInTree()
              {
                  NomenclatureCollection[0].IsExpanded = true;
                  NomenclatureCollection[0].Children[0].IsExpanded = true;
                   
                  var nomenclatureViewModel = NomenclatureCollection[0].Children[0].Children[0];
       
                  // ISSUE IS HERE -
                      nomenclatureViewModel.IsExpanded = true;
                  // ISSUE IS HERE
              }
          }
    4. And last but not least, I create in MainWindow 2 elements - RadTreeView and RadButton, that calls command "SelectCommand" in ViewModel.
      Note, i use ContainerBindingCollection for set IsLoadOnDemandEnabled, IsSelected and IsExpanded propertyes in TwoWay mode.
      <UserControl x:Class="RadControlsSilverlightApp1.MainPage"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                   xmlns:MVVMLightCommand="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4"
                   xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
                   xmlns:ViewModel="clr-namespace:RadControlsSilverlightApp1.ViewModel"
                   d:DesignHeight="800"
                   d:DesignWidth="400"
                   mc:Ignorable="d">
       
          <UserControl.Resources>
              <ViewModel:ViewModel x:Key="dataSource" />
          </UserControl.Resources>
       
          <Grid>
              <Grid.Resources>
                  <telerik:ContainerBindingCollection x:Name="BindingsCollection">
                      <telerik:ContainerBinding Binding="{Binding IsLoadOnDemandEnabled, Mode=TwoWay}" PropertyName="IsLoadOnDemandEnabled" />
                      <telerik:ContainerBinding Binding="{Binding IsSelected, Mode=TwoWay}" PropertyName="IsSelected" />
                      <telerik:ContainerBinding Binding="{Binding IsExpanded, Mode=TwoWay}" PropertyName="IsExpanded" />
                  </telerik:ContainerBindingCollection>
       
                  <telerik:HierarchicalDataTemplate x:Key="NodeTemplate"
                                                    ItemsSource="{Binding Children}"
                                                    telerik:ContainerBinding.ContainerBindings="{StaticResource BindingsCollection}">
                      <StackPanel Orientation="Horizontal">
                          <TextBlock Text="{Binding NomenclaturalUnit.Name}" />
                          <TextBlock Text=" [" />
                          <TextBlock FontWeight="Bold" Text="{Binding NomenclaturalUnit.ID}" />
                          <TextBlock Text="]" />
                      </StackPanel>
                  </telerik:HierarchicalDataTemplate>
              </Grid.Resources>
              <Grid.RowDefinitions>
                  <RowDefinition Height="Auto" MinHeight="25" />
                  <RowDefinition />
              </Grid.RowDefinitions>
       
              <StackPanel>
                  <telerik:RadButton Content="Expand in ViewModel"
                                     FontWeight="Bold"
                                     Padding="1">
                      <i:Interaction.Triggers>
                          <i:EventTrigger EventName="Click">
                              <MVVMLightCommand:EventToCommand Command="{Binding SelectCommand, Source={StaticResource dataSource}}" />
                          </i:EventTrigger>
                      </i:Interaction.Triggers>
                  </telerik:RadButton>
       
                  <telerik:RadButton Click="RadButton_Click"
                                     Content="Expand from code-behind"
                                     FontWeight="Bold"
                                     Padding="1" />
              </StackPanel>
       
       
              <telerik:RadTreeView x:Name="radTreeView"
                                   Grid.Row="1"
                                   IsVirtualizing="True"
                                   ItemsSource="{Binding NomenclatureCollection, Source={StaticResource dataSource}}"
                                   ItemTemplate="{StaticResource NodeTemplate}"
                                   telerik:AnimationManager.IsAnimationEnabled="False"
                                   telerik:TextSearch.TextPath="NomenclaturalUnit.ID"
                                   telerik:TreeViewPanel.VirtualizationMode="Recycling">
                  <i:Interaction.Triggers>
                      <i:EventTrigger>
                          <i:InvokeCommandAction Command="{Binding LoadedCommand, Source={StaticResource dataSource}}" />
                      </i:EventTrigger>
                      <i:EventTrigger EventName="LoadOnDemand">
                          <MVVMLightCommand:EventToCommand Command="{Binding LoadOnDemandCommand, Source={StaticResource dataSource}}" PassEventArgsToCommand="True" />
                      </i:EventTrigger>
                  </i:Interaction.Triggers>
              </telerik:RadTreeView>
          </Grid>
      </UserControl>
    5. The code shows the place where I find the problem. Trigger "LoadOnDemand" is not called, although it called on mouse click. We have the problem exactly at LOD item. Others nodes, not LOD-items, are expanded well. Note that if you call the same action from code-behind (it couldn't be done in my application becouse all logic has to be in the ViewModel because of specified reasons) - everything will work, as I mentioned in my previous message.

    I hope it helps clarify the problem.

    Thank you and again and I so sorry for my English =)

    P.S. I can not attach my solution...
  5. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 22 Nov 2011 Link to this post

    Hello Doxxer,

     We can see that you set the LoadingOnDemand to false when the Load operation completes:

    serviceClient.GetProductsFromSGroupCompleted +=
                            (s, args) =>
                            {
                                foreach (var item in args.Result)
                                {
                                    sGroup.Children.Add(item);
                                }
                                foreach (var nomenclatureViewModel in sGroup.Children.Select(child => new NomenclatureViewModel(child)))
                                {
                                    unitViewModel.Children.Add(nomenclatureViewModel);
                                }
                                e.Handled = true;
                                unitViewModel.IsLoadOnDemandEnabled = false;
                                LoadingOnDemand = false;
      
                            };
    but you haven't bound it. Why not make this property 9 or similar one) part of NomenclatureViewModel  and bind it to the IsLoadingOnDemand property of the RadTreeViewitem via ContainerBindings? Usually, in non-MVVM scenarios this property has to be set after the loading completes. Please let us know if this helped you.

    Best wishes,
    Petar Mladenov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  6. Niladri
    Niladri avatar
    1 posts
    Member since:
    Nov 2011

    Posted 29 Nov 2011 Link to this post

    Hello,

    I am newbie to the Silverlight. So, my question may look very silly to experienced guys, but believe me, I need your help to sort tis out.

    I have the following in my XAML
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4">
    

    And here is EventToCommand
    <cmd:EventToCommand Command="{Binding SelectTimeStudyCommand}" PassEventArgsToCommand="True" />
    

    When I am running the project I am getting the following error:

    The type 'EventToCommand' was not found because 'clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4' is an unknown namespace.

    And here is the full snippet of the CheckBox column

    <telerik:GridViewCheckBoxColumn DataMemberBinding="{Binding Path=IsSelected}" Header="Select">
      <i:Interaction.Triggers>
         <i:EventTrigger EventName="PropertyChanged">
             <cmd:EventToCommand Command="{Binding SelectTimeStudyCommand}" PassEventArgsToCommand="True" />
         </i:EventTrigger>
      </i:Interaction.Triggers>
    </telerik:GridViewCheckBoxColumn>

    Please help me ! Thanks in advance,

    Best regards,
    Niladri
  7. Jimmy
    Jimmy avatar
    2 posts
    Member since:
    May 2011

    Posted 30 Nov 2011 Link to this post

    Hi,

    I am having (maybe similar) problem on expanding a load-on-demand treeview item from the ViewModel. I have the IsExpanded property of the RadTreeViewItem binding setup as TwoWay. After IsExpanded is set to true in the ViewModel, the load on demand logic is triggered but visually, the item's Expander just spans and the item never gets expanded - see attached.

    The attached screenshot is produced based on the code TreeViewContainerBindings.zip from
     http://www.telerik.com/community/forums/silverlight/treeview/opening-treeview-in-expanded-mode.aspx with updates on the following three files.

    Start the app and click on the "Expand Item 3" button will reproduce the behavior shown on the attached screen shot. What am I missing to make the item expand?

    Thanks.

     1. MainPage.xaml
    <UserControl.Resources>
        <telerik:ContainerBindingCollection x:Key="TreeBindingsCollection">
            <telerik:ContainerBinding Binding="{Binding IsExpanded, Mode=TwoWay}" PropertyName="IsExpanded" />
            <telerik:ContainerBinding Binding="{Binding IsLoadingOnDemand}" PropertyName="IsLoadingOnDemand" />
            <telerik:ContainerBinding Binding="{Binding IsLoadOnDemandEnabled}"
                                      PropertyName="IsLoadOnDemandEnabled" />
        </telerik:ContainerBindingCollection>
     
        <telerik:HierarchicalDataTemplate x:Key="ItemTemplate"
                                          ItemsSource="{Binding Children}"
                                          telerik:ContainerBinding.ContainerBindings="{StaticResource TreeBindingsCollection}">
            <TextBlock Text="{Binding Header}" />
        </telerik:HierarchicalDataTemplate>
    </UserControl.Resources>
    <UserControl.DataContext>
        <local:ViewModel />
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
         
        <telerik:RadButton Content="Expand Item 3"
                           Command="{Binding ExpandItemCommand}"
                           Grid.Row="0">
        </telerik:RadButton>
         
        <telerik:RadTreeView x:Name="radTreeView"
                             IsLoadOnDemandEnabled="True"
                             SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                             ItemTemplate="{StaticResource ItemTemplate}"
                             ItemsSource="{Binding Items}"
                             IsExpandOnSingleClickEnabled="True"
                             Grid.Row="1">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="LoadOnDemand">
                    <i:InvokeCommandAction Command="{Binding ItemExpandedCommand}" CommandParameter="{Binding SelectedItem.Header}" />
                </i:EventTrigger>
                <i:EventTrigger EventName="ItemPrepared">
                    <i:InvokeCommandAction Command="{Binding ItemPreparedCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </telerik:RadTreeView>
     
    </Grid>

    2. ViewModel.cs
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Telerik.Windows.Controls;
    using System.Collections.ObjectModel;
     
    namespace _314398_TreeViewExample
    {
        public class ViewModel : ViewModelBase
        {
            public ViewModel()
            {
                ItemExpandedCommand = new DelegateCommand((a) => { this.LoadOnDemandCommand(a.ToString()); }, (p) => { return true; });
                ItemPreparedCommand = new DelegateCommand((a) => { }, (p) => { return true; });
                ExpandItemCommand = new DelegateCommand((a) => { this.ExpandItem(); }, (p) => { return true; });
     
                Items = new ObservableCollection<DataItem>();
     
                for (int i = 0; i < 8; i++)
                {
                    DataItem item = new DataItem()
                    {
                        Header = String.Format("Item {0}", i), IsLoadOnDemandEnabled = true
                    };
                    Items.Add(item);
                }
     
                this.SelectedItem = this.Items[0];
            }
             
            private DataItem selectedItem;
            public DataItem SelectedItem
            {
                get
                {
                    return this.selectedItem;
                }
                set
                {
                    if (this.selectedItem != value)
                    {
                        this.selectedItem = value;
                        OnPropertyChanged("SelectedItem");
                    }
                }
            }
     
            public DelegateCommand ItemExpandedCommand { get; set; }
            public DelegateCommand ItemPreparedCommand { get; set; }         
            public DelegateCommand ExpandItemCommand { get; set; }
     
            private void LoadOnDemandCommand(string param)
            {
                foreach (DataItem item in Items)
                {
                    if (item.Header == param)
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            item.Children.Add(new DataItem() { Header = String.Format("{0}.{1}", item.Header, i), IsLoadingOnDemand = false });
                        }
                        item.IsLoadingOnDemand = false;
                    }
                }
     
            }
     
            private void ExpandItem()
            {
                foreach (DataItem item in Items)
                {
                    if (item.Header == "Item 3")
                    {
    // this does triggers LoadOnDemandCommand, but the treeItem doesn't expand.
                        item.IsExpanded = true;
                    }
                }
            }
     
            public ObservableCollection<DataItem> Items { get; set; }
        }
    }

    3. DataItem.cs
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using Telerik.Windows.Controls;
     
    namespace _314398_TreeViewExample
    {
        public class DataItem : ViewModelBase
        {
            public DataItem()
            {
                this.Children = new ObservableCollection<DataItem>();
            }
     
            private bool isLoadOnDemandEnabled;
            public bool IsLoadOnDemandEnabled
            {
                get
                {
                    return this.isLoadOnDemandEnabled;
                }
                set
                {
                    if (this.isLoadOnDemandEnabled != value)
                    {
                        this.isLoadOnDemandEnabled = value;
                        OnPropertyChanged("IsLoadOnDemandEnabled");
                    }
                }
            }
     
            private bool isLoadingOnDemand;
            public bool IsLoadingOnDemand
            {
                get
                {
                    return this.isLoadingOnDemand;
                }
                set
                {
                    if (this.isLoadingOnDemand != value)
                    {
                        this.isLoadingOnDemand = value;
                        OnPropertyChanged("IsLoadingOnDemand");
                    }
                }
            }
     
            private bool isExpanded;
            public bool IsExpanded
            {
                get
                {
                    return this.isExpanded;
                }
                set
                {
                    if (this.isExpanded != value)
                    {
                        this.isExpanded = value;
                        OnPropertyChanged("IsExpanded");
                    }
                }
            }
     
            private string header;
            public string Header
            {
                get
                {
                    return this.header;
                }
                set
                {
                    if (this.header != value)
                    {
                        this.header = value;
                        OnPropertyChanged("Header");
                    }
                }
            }
     
            public ObservableCollection<DataItem> Children { get; set; }
        }
    }

  8. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 02 Dec 2011 Link to this post

    Hi guys,

    @Niladri - Unfortunately I cannot be sure what is causing this exception based only on the code snippets you sent. Can you try to isolate the issue in a small sample and send it to us? Also, in this forum thread you can find a sample solution using EventToCommand to implement an MVVM approach for customize the DragDrop behavior of the RadTreeView. The solution might help you find the cause for the exception in your project.

    @Jimmy - Thank you for sending your code. While I examined it I noticed that the LoadOnDemandCommand receives the header of the selected RadTreeViewItem as a parameter. However, when you click the Expand button, the selected item still remains the first item in the RadTreeview control. And then the LoadOnDemand logic tries to expand the 3rd item, while popupating the 1st RadTreeViewItems.ItemsSource colelction. This is why you get the loading animation which cannot end as the 3rd RadTreeViweItem.ItemsSource collection is never populated. Basically you need to make sure in your scenario, that the item that will be expanded is also selected. For example you can create an IsSelected property in the DataItem class and bind the RadTreeViewItem.IsSelected property to it:
    <telerik:ContainerBindingCollection x:Key="TreeBindingsCollection">
        <telerik:ContainerBinding Binding="{Binding IsExpanded, Mode=TwoWay}" PropertyName="IsExpanded" />
        <telerik:ContainerBinding Binding="{Binding IsSelected, Mode=TwoWay}" PropertyName="IsSelected" />
        <telerik:ContainerBinding Binding="{Binding IsLoadingOnDemand}" PropertyName="IsLoadingOnDemand" />
        <telerik:ContainerBinding Binding="{Binding IsLoadOnDemandEnabled}" PropertyName="IsLoadOnDemandEnabled" />
    </telerik:ContainerBindingCollection>
    Then you can set the DataItems IsSelected property to True before setting their IsExpanded property to true.

    I hope this information helps. But please let me know if you have more questions.

    Regards,
    Tina Stancheva
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  9. Jimmy
    Jimmy avatar
    2 posts
    Member since:
    May 2011

    Posted 02 Dec 2011 Link to this post

    @Tina, it works. Thank you.
Back to Top
DevCraft banner