|
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.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.