Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@dotMorten
Last active June 23, 2016 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dotMorten/30738245cffb9782cb45ac598fbfaf5e to your computer and use it in GitHub Desktop.
Save dotMorten/30738245cffb9782cb45ac598fbfaf5e to your computer and use it in GitHub Desktop.
StaggeredGrid
<ItemsControl x:Name="items" Grid.RowSpan="3" ItemsSource="{x:Bind Data}" Background="LightGray">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:StaggeredGridPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5" Background="{Binding Brush}" Height="{Binding Height}">
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public class TestData
{
public string Name { get; set; }
public SolidColorBrush Brush { get; set; }
public double Height { get; set; }
}
public List<TestData> Data
{
get
{
Random r = new Random();
var d = new List<TestData>();
for (int i = 0; i < 30; i++)
{
d.Add(new TestData() { Name = (i+1).ToString(), Brush = new SolidColorBrush(Windows.UI.Color.FromArgb(255,(byte)(255d/30*i),0, (byte)(255 - (255d / 30 * i)))), Height = r.Next(50, 200) });
}
return d;
}
}
public class StaggeredGridPanel : Panel
{
protected override Size ArrangeOverride(Size finalSize)
{
int cols = (int)Math.Floor(finalSize.Width / MaxColumnWidth);
var w = finalSize.Width / cols;
List<double> colHeight = new List<double>(cols);
for (int i = 0; i < cols; i++)
colHeight.Add(0);
foreach (var child in Children)
{
//use the shortest column
var col = colHeight.IndexOf(colHeight.Min());
double x = w * col;
double y = colHeight[col];
child.Arrange(new Rect(x, y, w, child.DesiredSize.Height));
colHeight[col] += child.DesiredSize.Height;
}
return new Size(finalSize.Width, colHeight.Max());
}
protected override Size MeasureOverride(Size availableSize)
{
int cols = (int)Math.Floor(availableSize.Width / MaxColumnWidth);
var w = availableSize.Width / cols;
availableSize = new Size(w, availableSize.Height);
List<double> colHeight = new List<double>(cols);
for (int i = 0; i < cols; i++)
colHeight.Add(0);
foreach (var child in Children)
{
child.Measure(availableSize);
//use the shortest column
var col = colHeight.IndexOf(colHeight.Min());
colHeight[col] += child.DesiredSize.Height;
}
return new Size(availableSize.Width, colHeight.Max());
}
public double MaxColumnWidth
{
get { return (double)GetValue(MaxColumnWidthProperty); }
set { SetValue(MaxColumnWidthProperty, value); }
}
public static readonly DependencyProperty MaxColumnWidthProperty =
DependencyProperty.Register(nameof(MaxColumnWidth), typeof(double), typeof(StaggeredGridPanel), new PropertyMetadata(300d, OnMaxColumnWidthPropertyChanged));
private static void OnMaxColumnWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((StaggeredGridPanel)d).InvalidateMeasure();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment