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.
  3. UI for WinForms is Visual Studio 2017 Ready
Back to Top