RadTreeView Selected Item Issue

6 posts, 0 answers
  1. Brian
    Brian avatar
    11 posts
    Member since:
    Sep 2012

    Posted 28 Apr 2014 Link to this post

    We have two RadTreeViews on a form. Tree1 contains a list of items (single level) that can be added to different groups in Tree2. Assume the following default tree items:

    Tree 1 (these items are static and cannot change. If you drag and drop, it copies the item instead of moving)
    ------------
    Item 1
    Item 2
    Item 3
    etc...

    Tree 2
    ------------
    Group A
    Group B
    Group C

    Say I drag 'Item 1' to add it to both 'Group A' and 'Group B'. So Tree 2 now looks like:

    Group A
    - Item 1
    Group B
    - Item 1
    Group C

    If I click to select 'Item 1' in 'Group B' it selects 'Item 1' in 'Group A'. It seems like when making a selection, it searches the tree from the top-down for the item that was clicked on and selects the first occurrence. So if I ever try to drag 'Item 1' from 'Group B' and move it to 'Group C', it will actually move 'Item 1' from 'Group A' to 'Group C'.

    I apologize if that seems confusing, not sure if I can explain it any better though. It's a really strange behavior and I'm sure it is not intended; however, I may be doing something wrong as well. I created 'HierarchicalDataTemplate' and 'DataTemplate' to set how the data displays my view model. I am also using the 'new' DragDropManager as well. The version of components we are using is 2013.3.1316.45 (we decided to not renew the license so this is the latest version available to us).

    Is there something I could be doing wrong? Is there a work around I could use?

    Thanks for any help
  2. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 30 Apr 2014 Link to this post

    Hi Brian,

    Thank you for the explanation.

    The reported behavior is caused by the fact that when you use the default drag and drop behavior of the RadTreeView and when you drag copy an item the tree won't create a new item but will add the same item at the drop position. Then when you select an item, the internal selection logic of the treeview will search for the selected item and if you have two (or more) items of the same instance, the tree will select the first found. 

    In order to avoid this behavior you can reconfigure the default drag and drop behavior of the RadTreeView to make a deep copy of the dragged item and drop the copy. You can take a look at the Copy Item When Dragging Within The Same Tree section from the Implement Copy Drag help article, which demonstrates such implementation. In addition I attached a sample project with a similar approach like in the article. Note that you will need to enable the drag drop of the tree views after attaching your drag/drop event handlers. Otherwise this approach won't work correctly.
    DragDropManager.AddDragOverHandler(this.treeB, OnDragOverBTree, true);
    DragDropManager.AddDragDropCompletedHandler(this.treeA, OnDropComplete, true);
     
    this.treeA.IsDragDropEnabled = true;
    this.treeB.IsDragDropEnabled = true;

    Please let me know if this helps.

    Regards,
    Martin
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Brian
    Brian avatar
    11 posts
    Member since:
    Sep 2012

    Posted 30 Apr 2014 in reply to Martin Link to this post

    Thanks for your help.

    After looking at it some more, the issue isn't necessarily with my drag drop process. It's the actual selection of an item (when clicking on it). I'm loading the two trees from a view model that connects to my database (the particular part of the database I'm working with has a many-to-many relationship). So for example say we have the standard 'Products' table and a 'Orders' table, then the table in between for 'OrderProducts'. In my treeview I have the 'Orders' as the group and I want to list the products for each order. The problem is when you said:

    "Then when you select an item, the internal selection logic of the treeview will search for the selected item and if you have two (or more) items of the same instance, the tree will select the first found."

    So basically if I select a product from order/group 2, then it is going to select the same product from order/group 1 instead. You can see that's obviously not the desired behavior. I would understand if you are searching the entire tree for a specific object that it'd behave that way. But when I actually click on an item in group 2, why would it have to search the tree for the item I'm actually clicking on? And if for some reason it does have to search, wouldn't it be better to search the current parent group for the item I clicked instead of the entire tree?

    I'm not real sure how to even tackle this. I'll post some code after while after I make some modifications. Thanks again.
  5. Brian
    Brian avatar
    11 posts
    Member since:
    Sep 2012

    Posted 30 Apr 2014 in reply to Brian Link to this post

    Below is an example of my view model given the 'Order/Product' scenario from my previous post:

    public class MyViewModel : ViewModelBase
    {
        public class OrderGroup
        {
            public dbOrder OrderInfo { get; set; }
            public ObservableCollection<dbProduct> OrderProducts { get; set; }
     
            public OrderGroup(dbOrder order)
            {
                this.OrderInfo = order;
                OrderProducts = new ObservableCollection<dbProduct>();
                foreach (dbProduct product in order.dbOrderProducts.Select(x => x.dbProduct))
                    this.OrderProducts.Add(product);
            }
        }
     
        public ObservableCollection<OrderGroup> OrderGroups { get; set; }
     
        public List<dbProduct> AvailableProducts { get; set; }
     
        public MyViewModel()
        {
            OrderGroups = new ObservableCollection<OrderGroup>();
            using (MyEntities entities = new MyEntities())
            {
                AvailableProducts = new List<dbProduct>(entities.dbProduct);
     
                foreach (dbOrder order in entities.dbOrder)
                    OrderGroups.Add(new OrderGroup(order));
            }
        }
    }

    And my data templates and tree definitions:

    <DataTemplate x:Key="tree_ProductNode">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding ItemNumber}"/>
        </StackPanel>
    </DataTemplate>
     
    <HierarchicalDataTemplate x:Key="tree_OrderNode" ItemTemplate="{StaticResource tree_ProductNode}" ItemsSource="{Binding OrderProducts}">
        <TextBlock Text="{Binding OrderNumber}"/>
    </HierarchicalDataTemplate>
     
     
    <telerik:RadTreeView Name="orderTree" SelectionMode="Extended" IsDragDropEnabled="True" ItemTemplate="{StaticResource tree_OrderNode}" ItemsSource="{Binding OrderGroups}" telerik:TreeViewSettings.DragDropExecutionMode="New">
    <telerik:RadTreeView Name="availableProducts" SelectionMode="Extended" IsDragDropEnabled="True" ItemTemplate="{StaticResource tree_ProductNode}" ItemsSource="{Binding AvailableProducts}" telerik:TreeViewSettings.DragDropExecutionMode="New"/>


    We have 'AvailableProducts' bound to one tree and 'OrderGroups' bound to another. Our particular issue is the 'OrderGroups' tree. Is there something I should be doing differently? Any help or direction you can provide would be great.

    Thanks,
  6. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 01 May 2014 Link to this post

    Hello Brian,

    Note that when you click an item in order to select it, the selection logic of the tree will get the DataContext of the clicked item and traverse recursively the tree to find the RadTreeViewItem which has this DataContext, and then select the found item. This means that if you have two items of the same instance (they point to the same location in the memory) the item that is higher in the tree hierarchy will be selected. For example, if you have the following tree:
    -Item 1
     -Item 1.2
     -Item 1.3 // same instance as Item 2 --> Item 1.3
    -Item 2
     -Item 2.1
     -Item 1.3 // same instance as Item 1 --> Item 1.3
    -Item 3

    and click "Item 1.3"  from the children of "Item 2" node, the "Item 1.3" from the children of "Item 1" node will be selected.

    If you don't want this behavior to appear you will need to create a new instance for each business object from the tree's collection before you pass it to the tree. Here is an example code:

    public OrderGroup(dbOrder order)
    {
        this.OrderInfo = order;
        OrderProducts = new ObservableCollection<dbProduct>();
        foreach (dbProduct product in order.dbOrderProducts.Select(x => x.dbProduct))
        {
            dbProduct newProduct = new dbProduct();
            newProduct.Name = product.Name;
             
            // copy whatever other properties you have in your product model and then add it in the OrderProducts      
             
            this.OrderProducts.Add(newProduct);
        }
    }
    In addition I updated the last project that I send you. Please give it a try and let me know if it helps. If not, can you send me an isolated project which includes your view models and part of your data, and also demonstrates the described behavior. This will help me in understanding your scenario better. 

    Regards,
    Martin
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  7. Brian
    Brian avatar
    11 posts
    Member since:
    Sep 2012

    Posted 01 May 2014 in reply to Martin Link to this post

    Awesome I understand what's going on now. I've finally got it working right. Thanks a lot for your help.
Back to Top
UI for WPF is Visual Studio 2017 Ready