Click here to Skip to main content
15,896,153 members
Articles / Programming Languages / C#

Silverlight ListBox Part II (Drag and drop in the same listbox and scroll)

Rate me:
Please Sign up or sign in to vote.
4.60/5 (2 votes)
8 Mar 2009CPOL3 min read 51.8K   893   13  
This article is about some of the issues like drag and drop in the same listbox and scrolling.
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.Generic;
using System.Diagnostics;

namespace MultipleDataTemplateInListBox
{
    public class WrapPanel : Panel
    {
        private static readonly DependencyProperty WrapPanelAttachedDataProperty =
           DependencyProperty.RegisterAttached("WrapPanelAttachedDataProperty", typeof(WrapPanelAttachedData), typeof(WrapPanel), null);

        private readonly List<double> rowHeights = new List<double>();

        // To maintain the row no. for each item.
        private readonly Dictionary<int, int> indexRowMapping = new Dictionary<int, int>();

        public double GetOffsetFromTop(int indexOfItem)
        {
            double offset = 0;
            if (!this.indexRowMapping.ContainsKey(indexOfItem))
            {
                return 0;
            }

            // Get the row no. for the given item.
            int rowNo = this.indexRowMapping[indexOfItem];

            // If row no. is 0 then offset would be 0.
            if (rowNo == 0)
            {
                return 0;
            }
            else
            {
                // Add the height of the rows which are before the row of the given element.
                for (int index = rowNo - 1; index >= 0; index--)
                {
                    offset += this.rowHeights[index];
                }
            }

            return offset;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (FrameworkElement child in this.Children)
            {
                child.Measure(availableSize);
            }

            double rowHeight = 0;
            int row = 0;
            int elementNo = 0;
            this.rowHeights.Clear();
            this.indexRowMapping.Clear();

            Size desiredSize = Size.Empty;

            Point nextChildPosition = new Point(0, 0);

            foreach (FrameworkElement child in this.Children)
            {
                if (nextChildPosition.X + child.DesiredSize.Width > availableSize.Width)
                {
                    this.rowHeights.Add(rowHeight);
                    ++row;

                    nextChildPosition.X = 0;
                    nextChildPosition.Y += rowHeight;
                    rowHeight = 0;
                }

                // Insert the index of the item and the row no.
                this.indexRowMapping.Add(elementNo, row);
                elementNo++;

                WrapPanelAttachedData data = GetWrapPanelAttachedData(child);

                if (data.TargetPosition != nextChildPosition)
                {
                    data.TargetPosition = nextChildPosition;
                    data.Row = row;
                }

                desiredSize.Width = Math.Max(desiredSize.Width, nextChildPosition.X + child.DesiredSize.Width);
                desiredSize.Height = Math.Max(desiredSize.Height, nextChildPosition.Y + child.DesiredSize.Height);

                rowHeight = Math.Max(rowHeight, child.DesiredSize.Height);

                nextChildPosition.X += child.DesiredSize.Width;
            }

            this.rowHeights.Add(rowHeight);

            return desiredSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement child in this.Children)
            {
                WrapPanelAttachedData data = GetWrapPanelAttachedData(child);
                child.Arrange(new Rect(data.TargetPosition.X, data.TargetPosition.Y, child.DesiredSize.Width, this.rowHeights[data.Row]));
            }

            return finalSize;
        }

        private static WrapPanelAttachedData GetWrapPanelAttachedData(DependencyObject obj)
        {
            object value = obj.GetValue(WrapPanelAttachedDataProperty);

            if (value == null)
            {
                WrapPanelAttachedData data = new WrapPanelAttachedData();
                SetAnimatedWrapPanelAttachedData(obj, data);
                return data;
            }

            return (WrapPanelAttachedData)value;
        }

        private static void SetAnimatedWrapPanelAttachedData(DependencyObject obj, WrapPanelAttachedData value)
        {
            obj.SetValue(WrapPanelAttachedDataProperty, value);
        }

        private class WrapPanelAttachedData
        {
            public static readonly Point Unset = new Point(-1, -1);

            public WrapPanelAttachedData()
            {
                this.TargetPosition = Unset;
            }

            public Point TargetPosition { get; set; }

            public int Row { get; set; }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Microsoft India
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions