Checkbox Parent gets unchecked when loading checked children

4 posts, 0 answers
  1. tsmithtn
    tsmithtn avatar
    8 posts
    Member since:
    May 2007

    Posted 11 Nov 2011 Link to this post

    Im trying to hard to get a treeview that has loading on demand enabled with checkboxes. I run into issues if I have a parent node checked and then try to expand it (which triggers a load on demand operation).  If the parent was checked, I build the children and make sure they have the checked property as well. When all is complete, the treeview successfully loads the children, the children are all checked as expected, but the parent node (that was expanded) gets unchecked! WHY?!

    <UserControl.Resources>
                <telerik:ContainerBindingCollection x:Key="TreeBindings">
            <telerik:ContainerBinding PropertyName="IsChecked" Binding="{Binding IsChecked, Mode=TwoWay}"/>
        </telerik:ContainerBindingCollection>
          
        <telerik:HierarchicalDataTemplate x:Key="TreeItemTemplate" ItemsSource="{Binding Children}" telerik:ContainerBinding.ContainerBindings="{StaticResource TreeBindings}">
            <TextBlock Text="{Binding DisplayName}" />
        </telerik:HierarchicalDataTemplate>
    </UserControl.Resources>
      
    <Grid x:Name="LayoutRoot" Margin="10">
                <telerik:RadTreeView SelectionMode="Single"  Grid.Row="1"
                ItemTemplate="{StaticResource TreeItemTemplate}"
                ItemsSource="{Binding ProcessTreeRoot}" 
                ItemPrepared="processSelectTree_ItemPrepared"               IsLoadOnDemandEnabled="True" LoadOnDemand="processSelectTree_LoadOnDemand"
                ItemsOptionListType="CheckList" 
                IsOptionElementsEnabled="True" 
                IsExpandOnSingleClickEnabled="False" 
                telerik:ContainerBinding.ContainerBindings="{StaticResource TreeBindings}"
                Margin="10" x:Name="processSelectTree" IsTriStateMode="True">
              
        </telerik:RadTreeView>
    </Grid>

    My relavant code behind :

    private void processSelectTree_LoadOnDemand(object sender, Telerik.Windows.RadRoutedEventArgs e)
    {
        RadTreeViewItem treeitem = e.OriginalSource as RadTreeViewItem;
        (DataContext as DocumentAssignmentByProcessViewModel).LoadChildrenOnDemandCommand.Execute(treeitem.Item as PlantConfigTreeItem);
    }
    private void processSelectTree_ItemPrepared(object sender, Telerik.Windows.Controls.RadTreeViewItemPreparedEventArgs e)
    {
        RadTreeViewItem treeitem = (RadTreeViewItem)e.PreparedItem;
        treeitem.IsLoadOnDemandEnabled = (treeitem.Item as PlantConfigTreeItem).HasChildren;
    }


    My View Model related code (command code triggered on load demand)

    protected void LoadChildrenOnDemand(PlantConfigTreeItem objTreeItem)
    {
        if (objTreeItem is LineTreeItem)
        {
        //  string userClockNum = (HandbookMode == enHandbookMode.ALL) ? "" : ECAPApplicationState.Instance.LoggedInAssociate.ClockNumber;
            prodContext.Load(prodContext.GetPositionsQuery("",
                ECAPApplicationState.Instance.CurrentDivisionPlantConfigId,
                objTreeItem.Id),
                io =>
                {
                    ObservableCollection<PlantConfigTreeItem> positionList = new ObservableCollection<PlantConfigTreeItem>();
                    foreach (Position pl in io.Entities ) 
                        positionList.Add(new PositionTreeItem { Id = pl.Id, DisplayName = pl.PositionTitle, HasChildren = true, IsChecked = objTreeItem.IsChecked });
                    AddRange( objTreeItem.Children, positionList);
                },
                null
            );
        }
        else if (objTreeItem is PositionTreeItem)
        {
            //  string userClockNum = (HandbookMode == enHandbookMode.ALL) ? "" : ECAPApplicationState.Instance.LoggedInAssociate.ClockNumber;
            prodContext.Load(prodContext.GetAllProcessQuery("",
                ECAPApplicationState.Instance.CurrentDivisionPlantConfigId,
                objTreeItem.Id),
                io =>
                {
                    ObservableCollection<PlantConfigTreeItem> positionList = new ObservableCollection<PlantConfigTreeItem>();
                    foreach (Process pl in io.Entities)
                        positionList.Add(new ProcessTreeItem { Id = pl.Id, DisplayName = pl.Name, HasChildren = false, IsChecked = objTreeItem.IsChecked });
                    AddRange(objTreeItem.Children, positionList);
                },
                null
            );
        }
    }






  2. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 16 Nov 2011 Link to this post

    Hi Tsmithtn,

    Unfortunately this is a known issue - it is logged in our PITS here. As a workaround you can try to reset the parent item check state in the processSelectTree_LoadOnDemand event handler using a Dispatcher:
    private void processSelectTree_LoadOnDemand(object sender, Telerik.Windows.RadRoutedEventArgs e)
    {
        RadTreeViewItem treeitem = e.OriginalSource as RadTreeViewItem;
        (DataContext as DocumentAssignmentByProcessViewModel).LoadChildrenOnDemandCommand.Execute(treeitem.Item as PlantConfigTreeItem);
     
        Dispatcher.BeginInvoke(new Action(() => { treeitem.IsChecked = true; }));
    }

    Give this approach a try and let us know if it helps.

    Kind regards,
    Tina Stancheva
    the Telerik team

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

  3. DevCraft banner
  4. tsmithtn
    tsmithtn avatar
    8 posts
    Member since:
    May 2007

    Posted 16 Nov 2011 Link to this post

    I had tried that approach to no avail. However, I did figure out order of events and was able to add code to the code behind to get it to work. Hopefully this will help someone else out as i saw this question posted several times without concrete solution.

    I changed my bindings to the CheckState property (as opposed to isChecked property). Final XAML below:
        <UserControl.Resources>
            <!-- Page Converters -->
            <converters:BooleanToToggleStateConverter x:Key="Bool2ToggleConverter" />
              
            <telerik:ContainerBindingCollection x:Key="TreeBindings">
                <telerik:ContainerBinding  PropertyName="CheckState" Binding="{Binding IsChecked, Mode=TwoWay, Converter={StaticResource Bool2ToggleConverter}}" />
                <telerik:ContainerBinding PropertyName="IsExpanded" Binding="{Binding IsExpanded, Mode=TwoWay}" />
            </telerik:ContainerBindingCollection>
              
            <telerik:HierarchicalDataTemplate x:Key="TreeItemTemplate" ItemsSource="{Binding Children}" telerik:ContainerBinding.ContainerBindings="{StaticResource TreeBindings}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding DisplayName}" />
                </StackPanel>
            </telerik:HierarchicalDataTemplate>
        </UserControl.Resources>
          
        <Grid x:Name="LayoutRoot" Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
      
                  
            <telerik:RadTreeView SelectionMode="Single"  Grid.Row="1"
                    ItemTemplate="{StaticResource TreeItemTemplate}"
                    ItemsSource="{Binding ProcessTreeRoot}" 
                    ItemPrepared="processSelectTree_ItemPrepared"
                    IsLoadOnDemandEnabled="True" LoadOnDemand="processSelectTree_LoadOnDemand"
                    ItemsOptionListType="CheckList"
                    IsOptionElementsEnabled="True" 
                    PreviewUnchecked="processSelectTree_PreviewUnchecked"
                    IsExpandOnSingleClickEnabled="True" 
                    telerik:ContainerBinding.ContainerBindings="{StaticResource TreeBindings}"
                    Checked="processSelectTree_Checked" Unchecked="processSelectTree_Checked"
                    Margin="0" 
                    x:Name="processSelectTree"
                    IsTriStateMode="True" />
      
        </Grid>
          
    </UserControl>

    The magic happens in my code behind. I set a flag to detect when a node is being expanded and not yet loaded. Since this event happens before the unwanted Unchecked event, I am able to use the PreviewUnchecked event to see if Im in this unwanted state. If I am, I simply throw that event away:

    {
        private bool bExpandingCheckedUnloadedItem_TelerikHack = false;
        public DocumentAssignmentByProcess()
        {
            InitializeComponent();
        }
        private void processSelectTree_LoadOnDemand(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            RadTreeViewItem treeitem = e.OriginalSource as RadTreeViewItem;
            (DataContext as DocumentAssignmentByProcessViewModel).LoadChildrenOnDemandCommand.Execute(treeitem.Item as PlantConfigTreeItem);
            // telerik tree hack. apparently if a node is checked (and not yet loaded), it will get unchecked when expanded
            if (treeitem.CheckState == System.Windows.Automation.ToggleState.On)
            {
                treeitem.IsChecked = true;
                bExpandingCheckedUnloadedItem_TelerikHack = true;
            }
        }
        private void processSelectTree_ItemPrepared(object sender, Telerik.Windows.Controls.RadTreeViewItemPreparedEventArgs e)
        {
            RadTreeViewItem treeitem = (RadTreeViewItem)e.PreparedItem;
            treeitem.IsLoadOnDemandEnabled = (treeitem.Item as PlantConfigTreeItem).HasChildren;
        }
        private void processSelectTree_PreviewUnchecked(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            // more of the hack.. after the tree node is expanded, the tree control for some reason unselects the parent node
            // this code checks for situatio where node was originally checked (indicated by bExpandingCheckedUnloadedItem) 
            // and will check it and cancel uncheck event
            if (bExpandingCheckedUnloadedItem_TelerikHack)
            {
                bExpandingCheckedUnloadedItem_TelerikHack = false;
                e.Handled = true;
                RadTreeViewItem treeitem = e.OriginalSource as RadTreeViewItem;
                treeitem.IsSelected = true;
            }
        }






  5. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 16 Nov 2011 Link to this post

    Hello Tsmithtn,

    Thank you for sharing your solution. I am sure it will be highly appreciated by the community.

    Kind regards,
    Tina Stancheva
    the Telerik team

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

Back to Top