Introduction
Shows how to apply a UniformGrid control in a simple Silverlight MVVM application.
Background
I was searching for a Silverlight layout control that would allow me to control how many items were displayed in each row of a wrap panel. In my actual application, I have several graphs that are identically sized and each row corresponds to an attribute. A standard wrap panel (Silverlight Toolkit) wouldn't work because it just wraps the items with no property to control how many items are in each row.
I found an excellent article by Jeff Wilcox where he ported a UniformGrid control from WPF to Silverlight. This was exactly what I needed. Jeff provided an example but I wanted to apply this control in an MVVM application where the control would layout items from a collection.
Using the code
See Jeff's page for full details on the control itself. The xaml looks like this:
<UserControl x:Class="SL_MVVM_UniformGridLayout.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
xmlns:models="clr-namespace:SL_MVVM_UniformGridLayout"
xmlns:local="clr-namespace:System.Windows.Controls.Primitives"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White" Width="500">
<StackPanel Orientation="Vertical">
<TextBlock Text="With Silverlight Toolkit Wrap Panel" Margin="10"/>
<StackPanel HorizontalAlignment="Left" Background="#FFEE9797" Margin="5">
<StackPanel.Resources>
<ItemsPanelTemplate x:Name="WrapPanel">
<toolkit:WrapPanel Width="490" >
</toolkit:WrapPanel>
</ItemsPanelTemplate>
</StackPanel.Resources>
<ItemsControl ItemsSource="{Binding MyStrings}" ItemsPanel="{StaticResource WrapPanel}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox HorizontalAlignment="Center" Width="75" TextAlignment="Center" Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<Rectangle Fill="#FFA5E7F1" Grid.Row="1" Height="10" />
<TextBlock Text="With UniformGrid" Margin="10"/>
<StackPanel HorizontalAlignment="Left" Background="#FF9F77F3" Margin="5">
<StackPanel.Resources>
<ItemsPanelTemplate x:Name="uniform">
<local:UniformGrid Columns="{Binding NumColumns}">
</local:UniformGrid>
</ItemsPanelTemplate>
</StackPanel.Resources>
<ItemsControl ItemsSource="{Binding MyStrings}" ItemsPanel="{StaticResource uniform}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox HorizontalAlignment="Center" Width="75" TextAlignment="Center" Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
The first section displays the bound data using a wrap panel from the Silverlight Toolkit. The seconds displays the same data with the UniformGrid control.
The Code behind:
using System.Windows.Controls;
namespace SL_MVVM_UniformGridLayout
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
MainPageViewModel vm = new MainPageViewModel();
this.DataContext = vm;
}
}
}
This just set the data context as the main view model, which also could have been done in the xaml.
And the View Model:
using System.Collections.Generic;
namespace SL_MVVM_UniformGridLayout
{
public class MainPageViewModel : ViewModelBase
{
public MainPageViewModel()
{
List<string> strings = new List<string>()
{"The", "Quick", "Brown", "Fox", "Jumped", "Over", "The",
"Lazy", "Dog", "Who", "Was", "Lethargic", "Beyond", "Belief"};
MyStrings = strings;
m_NumColumns = 3; }
#region Properties
List<string> myStrings;
public List<string> MyStrings
{
get { return myStrings; }
set
{ myStrings = value;
NotifyPropertyChanged("MyStrings");
}
}
int m_NumColumns;
public int NumColumns
{
get { return m_NumColumns; }
set
{
if (m_NumColumns == value)
{
return;
}
m_NumColumns = value;
NotifyPropertyChanged("NumColumns");
}
}
#endregion
}
}
A generic List and a couple of properties for binding to the view. I kept this example as simple as possible while demonstrating how the UniformGrid could be used to control the presentation of a bound collection. Hope this helps someone.
History
Initial.