Issue with rendering page after drag and drop

2 posts, 0 answers
  1. Ralf
    Ralf avatar
    1 posts
    Member since:
    Oct 2012

    Posted 18 Jan 2013 Link to this post

    Hello,

    I have an application were I include a Treeview.

    I have some issues with my screen,
    when I manipulate this treeview with drag and drop functionality.

    The treeview get's rendered and is only showing a part.
    It's like the scrollbar is not on the correct position.
    When I scroll with the mouse up and down it will be rendered correct again.

    This issue appear's when I reorder the treeview with the mouse, aswell in code.
    It's not predictable when it occurs.

    Has anyone an idea how to fix this ?

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Linq;
    using System.Windows.Forms;
    using Telerik.WinControls;
    using Telerik.WinControls.Data;
    using Telerik.WinControls.UI;
     
    namespace SortAccountsSpike
    {
        public partial class SortAccountsForm : Form
        {
            private Object _currentTargetDataBoundItem;
      
            public SortAccountsForm()
            {
                InitializeComponent();
              //  _dataList = new ObservableCollection<AccountGroup>();
            }
     
            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
                AutoScroll = false;
     
                radTreeView1.TreeViewElement.NodeFormatting += TreeViewElement_NodeFormatting;
                radTreeView1.DragStarting += RadTreeView1DragStarting;
                radTreeView1.DragOverNode += RadTreeView1DragOverNode;
                radTreeView1.DragEnding += RadTreeView1DragEnding;
                radTreeView1.TreeViewElement.AutoSizeItems = true;
                radTreeView1.ShowLines = true;
                radTreeView1.ShowRootLines = true;
                radTreeView1.ShowExpandCollapse = true;
                radTreeView1.FullRowSelect = true;
                radTreeView1.LineStyle = TreeLineStyle.Dot;
                radTreeView1.MultiSelect = true;
                radTreeView1.ShowNodeToolTips = true;
                radTreeView1.TreeViewElement.Comparer = new AccounNodeComparer(radTreeView1.TreeViewElement);
                radTreeView1.NodeExpandedChanging += radTreeView1_NodeExpandedChanging;
     
                FillTreeView();
            }
     
            private void FillTreeView()
            {
                radTreeView1.ChildMember = @"AccountGroup\Accounts";
              //  radTreeView1.DisplayMember = @"GroupName\AccountNumber";
                radTreeView1.SortOrder = SortOrder.Ascending;
                radTreeView1.DataSource = AccountModel.AccountGroups;
            }
     
            void TreeViewElement_NodeFormatting(object sender, TreeNodeFormattingEventArgs e)
            {
                var treeNodeContentElement = e.NodeElement.ContentElement;
     
                //General styling
                /////////////
      
                //  treeNodeContentElement.StretchHorizontally = true;
                treeNodeContentElement.Padding = new Padding(5);
                treeNodeContentElement.Margin = new Padding(0, 2, 0, 2);
                treeNodeContentElement.SmoothingMode = SmoothingMode.AntiAlias;
                treeNodeContentElement.DrawBorder = true;
                treeNodeContentElement.BorderColor = Color.FromArgb(110, 153, 210);
                treeNodeContentElement.DrawFill = true;
                treeNodeContentElement.GradientStyle = GradientStyles.Linear;
                treeNodeContentElement.NumberOfColors = 2;
     
                //AccountGroupFormatting
                var accountGroup = e.Node.DataBoundItem as AccountGroup;
                if (accountGroup != null)
                {
                    treeNodeContentElement.Text = accountGroup.ToDisplayHtml();
                    e.Node.Expanded = accountGroup.Expanded;
     
                    //fill
                    treeNodeContentElement.BackColor = Color.FromArgb(248, 248, 248);
                    treeNodeContentElement.BackColor2 = Color.FromArgb(233, 233, 233);
                }
     
                //Account formatting
                var accountInfo = e.Node.DataBoundItem as AccountInfo; 
                if (accountInfo != null)
                {
                    treeNodeContentElement.Text = accountInfo.ToDisplayHtml();
     
                    if (accountInfo.IsVisible)
                    {
                        e.Node.ToolTipText = string.Empty;
                        treeNodeContentElement.BackColor = Color.FromArgb(174, 190, 217);
                        treeNodeContentElement.BackColor2 = Color.FromArgb(168, 183, 210);
                        treeNodeContentElement.ForeColor = Color.Black;
                    }
                    else
                    {
                        e.Node.ToolTipText = "This account is not visible in drop down lists.";
                        treeNodeContentElement.BackColor = Color.FromArgb(227, 233, 242);
                        treeNodeContentElement.BackColor2 = Color.FromArgb(235, 238, 245);
                        treeNodeContentElement.ForeColor = Color.FromArgb(153, 153, 153);
                    }
     
                      
                }
            }
     
            void radTreeView1_NodeExpandedChanging(object sender, RadTreeViewCancelEventArgs e)
            {
                var group = e.Node.DataBoundItem as AccountGroup;
                if (group != null)
                {
                    group.Expanded = !e.Node.Expanded;
                }
            }
     
            void RadTreeView1DragStarting(object sender, RadTreeViewDragCancelEventArgs e)
            {
                //don't allow the first group to be moved
                if (e.Node.Level == 0 && e.Node.Index == 0)
                {
                    e.Cancel = true;
                }
         
                _currentTargetDataBoundItem = null;
            }
     
            void RadTreeView1DragOverNode(object sender, RadTreeViewDragCancelEventArgs e)
            {
                //determine if the dragged node can be dropped on the current hovered node
                if (e.Node != null)
                {
                    e.Cancel = !CanBeDroppedOnTarget(e.Node.DataBoundItem, e.TargetNode.DataBoundItem);
                }
                else
                {
                    e.Cancel = true;
                }
            }
     
            void RadTreeView1DragEnding(object sender, RadTreeViewDragCancelEventArgs e)
            {
                //recheck if it is correct to drop the dragged node on the target node (this event is fired multiple times when multiple nodes are dragged at once)
                if (CanBeDroppedOnTarget(e.Node.DataBoundItem, e.TargetNode.DataBoundItem))
                {
                    if (_currentTargetDataBoundItem == null)
                        _currentTargetDataBoundItem = e.TargetNode.DataBoundItem;
                    //execute drag operation      
                    MoveNode(e.Node.DataBoundItem);             
                }
            
                e.Cancel = true; //cancel event and make the treeview refresh to reflect the changed observable datasource
                radTreeView1.Nodes.Refresh();
                radTreeView1.SelectedNodes.Clear();
            }
     
            private bool CanBeDroppedOnTarget(Object draggedDataBoundItem, Object targetDataBoundItem)
            {
                var draggedGroup = draggedDataBoundItem as AccountGroup;
                var targetGroup = targetDataBoundItem as AccountGroup;
                if (draggedGroup != null)
                {
                    //dragged node is a group -> target must also be a group
                    return (targetGroup != null);
                }
                else
                {
                    //dragged node is an account
                    var draggedAccount = (AccountInfo)draggedDataBoundItem;
     
                    //-> if parent is also being dragged, the node cannot be dropped
                    var parentGroupIsAlsoDragged = radTreeView1.SelectedNodes.Select(n => n.DataBoundItem)
                                                               .OfType<AccountGroup>()
                                                               .Any(
                                                                   group =>
                                                                   group.Accounts.Any(
                                                                       account => account.Id == draggedAccount.Id));
     
                    return !parentGroupIsAlsoDragged;
                }
            }
     
            private void MoveNode(Object draggedDataBoundItem)
            {
                var draggedGroup = draggedDataBoundItem as AccountGroup;
                var targetGroup = _currentTargetDataBoundItem as AccountGroup;
                var draggedAccount = draggedDataBoundItem as AccountInfo;
                var targetAccount = _currentTargetDataBoundItem as AccountInfo;
                if (draggedGroup != null)
                {
                    if (targetGroup == null)
                    {
                        throw new InvalidOperationException(
                            "Dropping an account group on a node that does not represent an account group is not possible.");
                    }
     
                    MoveAccountGroup(draggedGroup, targetGroup);
                }
                else
                {
                    //move account
                    MoveAccount(draggedAccount, targetAccount, targetGroup);
                }
            }
     
            private void MoveAccount(AccountInfo draggedAccount, AccountInfo targetAccount, AccountGroup targetGroup)
            {
                Debug.Assert(draggedAccount != null);
     
                AccountGroup draggedGroup = AccountModel.AccountGroups.First(group => @group.Accounts.Contains(draggedAccount));
     
                if (targetAccount != null)
                {
                    targetGroup = AccountModel.AccountGroups.First(group => @group.Accounts.Contains(targetAccount));
                }
                Debug.Assert(targetGroup != null);
     
                //move down items
                var targetSequence = (targetAccount != null) ? targetAccount.Sequence : 0;
                var accountInfosToMove = targetGroup.Accounts.Where(accInfo => accInfo.Sequence > targetSequence);
                foreach (var accInfo in accountInfosToMove)
                {
                    accInfo.Sequence += 1;
                }
     
                //move item
                draggedAccount.Sequence = targetSequence + 1;
     
                if (draggedGroup.Id != targetGroup.Id)
                {
                    draggedGroup.Accounts.Remove(draggedAccount);
                    targetGroup.Accounts.Add(draggedAccount);
                    NormalizeAccountSequences(draggedGroup.Accounts);
                }
     
                NormalizeAccountSequences(targetGroup.Accounts);
     
                if (_currentTargetDataBoundItem is AccountInfo)
                {
                    _currentTargetDataBoundItem = draggedAccount;
                }
            }
     
            private void MoveAccountGroup(AccountGroup draggedGroup, AccountGroup targetGroup)
            {
                //move down items
                var groupsToMove = AccountModel.AccountGroups.Where(group => @group.Sequence > targetGroup.Sequence);
                foreach (var group in groupsToMove)
                {
                    @group.Sequence += 1;
                }
     
                //move group
                draggedGroup.Sequence = targetGroup.Sequence + 1;
     
                //normalize
                NormalizeGroupSequences(AccountModel.AccountGroups);
            }
     
            private void NormalizeAccountSequences(IEnumerable<AccountInfo> accountInfosToNormalize)
            {
                var index = 0;
     
                foreach (var accInfo in accountInfosToNormalize.OrderBy(account => account.Sequence))
                {
                    accInfo.Sequence = ++index;
                }
            }
     
            private void NormalizeGroupSequences(IEnumerable<AccountGroup> accountGroupsToNormalize)
            {
                var index = 0;
     
                foreach (var group in accountGroupsToNormalize.OrderBy(group => group.Sequence))
                {
                    group.Sequence = ++index;
                }
            }
     
     
            private void MakeVisibleButtonClick(object sender, EventArgs e)
            {
                ChangVisibilityOfSelectedNodes(true);
            }
     
            private void MakeInvisibleButtonClick(object sender, EventArgs e)
            {
                ChangVisibilityOfSelectedNodes(false);
            }
     
            private void ChangVisibilityOfSelectedNodes(bool isvisible)
            {
                var accountsToChange = radTreeView1.SelectedNodes.Select(n => n.DataBoundItem).OfType<AccountInfo>().ToList();
     
                foreach (var account in accountsToChange)
                {
                    account.IsVisible = isvisible;
                }
     
                radTreeView1.Nodes.Refresh();
            }
     
            private void ChangeAliasButtonClick(object sender, EventArgs e)
            {
                string filledInAlias = string.Empty;
     
                var uniquePreferedNames =
                    (from account in radTreeView1.SelectedNodes.Select(n => n.DataBoundItem).OfType<AccountInfo>()
                     group account by account.PreferedName
                     into accountGroup
                     select accountGroup.Key).ToList();
     
                if (uniquePreferedNames.Count == 1)
                {
                    filledInAlias = uniquePreferedNames.First();
                }
     
                var result = InputDialog.ShowInputBox("Edit alias", "Please fill in an alias for the selected account(s)", out filledInAlias, this, filledInAlias);
     
                if (result == DialogResult.OK)
                {
                    var accountsToChange = radTreeView1.SelectedNodes.Select(n => n.DataBoundItem).OfType<AccountInfo>().ToList();
     
                    foreach (var account in accountsToChange)
                    {
                        account.PreferedName = filledInAlias;
                    }
     
                    radTreeView1.Nodes.Refresh();
                }     
            }
     
            private static class AccountModel
            {
                private static ObservableCollection<AccountGroup> _accountGroups;
                public static ObservableCollection<AccountGroup> AccountGroups
                {
                    get { return _accountGroups ?? (_accountGroups = LoadInitialDataList()); }
                }
     
                private static ObservableCollection<AccountGroup> LoadInitialDataList()
                {
                    var dataCollection = new ObservableCollection<AccountGroup>();
                    var groupNone = new AccountGroup
                        {
                        Id = Guid.NewGuid(),
                        GroupName = "No group",
                        Sequence = 1,
                        Expanded = true
                    };
                    dataCollection.Add(groupNone);
     
                    var groupTest = new AccountGroup
                    {
                        Id = Guid.NewGuid(),
                        GroupName = "Some other group",
                        Sequence = 2
                    };
                    dataCollection.Add(groupTest);
     
                    var anotherGroup = new AccountGroup
                    {
                        Id = Guid.NewGuid(),
                        GroupName = "Yet another group",
                        Sequence = 3
                    };
                    dataCollection.Add(anotherGroup);
     
                    var item1 = new AccountInfo
                    {
                        Id = Guid.NewGuid(),
                        AccountNumber = "1",
                        Balance = 154000,
                        Currency = "EUR",
                        Product = "Alba VZW, Mullens Kris",
                        Sequence = 1,
                        IsVisible = true
                    };
                    groupNone.Accounts.Add(item1);
     
                    var item2 = new AccountInfo
                    {
                        Id = Guid.NewGuid(),
                        AccountNumber = "2",
                        Balance = 500,
                        Currency = "EUR",
                        Product = "John Doe",
                        PreferedName = "The unknown account",
                        Sequence = 3,
                        IsVisible = true
                    };
                    groupNone.Accounts.Add(item2);
     
                    var item3 = new AccountInfo
                    {
                        Id = Guid.NewGuid(),
                        AccountNumber = "3",
                        Balance = -600,
                        Currency = "EUR",
                        Product = "Jane Doe",
                        Sequence = 4
                    };
                    groupTest.Accounts.Add(item3);
     
                    var item4 = new AccountInfo
                    {
                        Id = Guid.NewGuid(),
                        AccountNumber = "4",
                        Balance = -600,
                        Currency = "EUR",
                        Product = "John Denver",
                        Sequence = 5
                    };
                    groupTest.Accounts.Add(item4);
     
                    var item5 = new AccountInfo
                    {
                        Id = Guid.NewGuid(),
                        AccountNumber = "5",
                        Balance = 600897,
                        Currency = "EUR",
                        Product = "Richie Vallens",
                        Sequence = 6,
                        IsVisible = true
                    };
                    groupTest.Accounts.Add(item5);
     
                    for (int i = 0; i < 10; i++)
                    {
                        var item6 = new AccountInfo
                        {
                            Id = Guid.NewGuid(),
                            AccountNumber = "BE11 2222 3333 4444",
                            Balance = -150,
                            Currency = "EUR",
                            Product = "Donna Summer",
                            Sequence = i + 1
                        };
                        anotherGroup.Accounts.Add(item6);
                    }
     
                    
     
                    return dataCollection;
                }
            }
        }
     
        public class AccounNodeComparer : TreeNodeComparer
        {
            public AccounNodeComparer(RadTreeViewElement treeViewElement)
                : base(treeViewElement)
            {
     
            }
     
            public override int Compare(RadTreeNode x, RadTreeNode y)
            {
                //compare 2 account groups
                var accountGroup1 = x.DataBoundItem as AccountGroup;
                var accountGroup2 = y.DataBoundItem as AccountGroup;
     
                if (accountGroup1 != null && accountGroup2 != null)
                {
                    return accountGroup1.CompareTo(accountGroup2);
                }
     
                //compare 2 accounts
                var accountInfo1 = x.DataBoundItem as AccountInfo;
                var accountInfo2 = y.DataBoundItem as AccountInfo;
     
                if (accountInfo1 != null && accountInfo2 != null)
                {
                    return accountInfo1.CompareTo(accountInfo2);
                }
     
                return 0;
            }
        }
    }

    Kind regards.

    Ralf

  2. Svett
    Admin
    Svett avatar
    728 posts

    Posted 22 Jan 2013 Link to this post

    Hello Ralf,

    Thank you for writing.

    I applied the sample code snippet in a project on my side. Nevertheless, I did not manage to reproduce the issue. I am enclosing a sample video that demonstrates my approach. Could you tell me the exact steps that I should follow? What did I miss?  Note that you need a web browser and installed flash plugin to watch the video.

    Regards,
    Svett
    the Telerik team
    Q3'12 SP1 of RadControls for WinForms is out now. See what's new.
Back to Top