65.9K
CodeProject is changing. Read more.
Home

Simple Silverlight MVVM Example using UniformGrid

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4 votes)

Oct 12, 2014

CPOL

1 min read

viewsIcon

10871

downloadIcon

177

A simple Silverlight application that shows how to apply Jeff Wilcox's UniformGrid control to a bound collection.

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
    {       
        //Constructor
        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;  //used with UniformGrid
        }

        #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.