Silverlight 2 Image Tiling

28 01 2009

Silverlight’s big brother WPF has a lot of functionality that you would like to have in Silverlight 2. One of these features is a Tiling Image Brush.

As many of you have probably already found out, it is impossible to create your own brush in Silverlight, because of internal and sealed base classes.

A couple of months a go I was working on a project which required images being tiled across the screen, so I decided to create a tiling control, which takes an image and puts as many as fit the screen into a wrap panel (from the silverlight control toolkit).

Since then I have seen a lot of people asking for this functionality, I though I would share this very simple (user) control. Below is the code, let me know if you have any questions or remarks.

There are still a few improvements you could make to this code. For example determining the width and height of the image automatically. But to keep it simple I left that code out.

The image used in this example is a random one I took from Google image search:

When finished it should look like something like this:

image

In the application: (local namespace should be added to the top of the xaml)

<local:ImageRepeater

   ImageSource="http://ecx.images-amazon.com/images/I/51sghWRypwL._SL75_SS50_.jpg"

   ImageWidth="50"

   ImageHeight="50"/>

UserControl: ImageRepeater.xaml

<UserControl x:Class="ImageRepeater"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"

    >

    <Grid x:Name="LayoutRoot" Background="White">

        <controls:WrapPanel x:Name="xRepeaterPanel"/>

    </Grid>

</UserControl>

UserControl: ImageRepeater.xaml.cs

public partial class ImageRepeater : UserControl

{

    public ImageRepeater()

    {

        InitializeComponent();

    }

 

    // The brush to paint on the rectangle

    private ImageBrush _BrushToTile = new ImageBrush();

    public ImageSource ImageSource

    {

        get { return _BrushToTile.ImageSource; }

        set {

            _BrushToTile.ImageSource = value;

        }

    }

 

    private double _ImageWidth;

    public double ImageWidth

    {

        get { return _ImageWidth; }

        set { _ImageWidth = value; }

    }

 

 

    private double _ImageHeight;

 

    public double ImageHeight

    {

        get { return _ImageHeight; }

        set { _ImageHeight = value; }

    }

 

    protected override Size ArrangeOverride(Size finalSize)

    {

        // To make sure that we fill the screen horizontally and vertically, we create negative margins

        Margin = new Thickness(0, 0, -ImageHeight, -ImageWidth);

 

        // Determine how many rectangles we need to add to fill the available screen width

        var itemCount = (int)Math.Ceiling(finalSize.Width / ImageWidth);

        itemCount = itemCount * (int)Math.Ceiling(finalSize.Height / ImageHeight);

 

        // It is done incrementally, so when the control is resized, we add more to it so fill the area again.

        var diff = itemCount - xRepeaterPanel.Children.Count();

        for (int i = 0; i < diff; i++)

        {

            // Create and add every rectangle

            var rect = new Rectangle();

            rect.Width = ImageWidth;

            rect.Height = ImageHeight;

            rect.Fill = _BrushToTile;

            xRepeaterPanel.Children.Add(rect);

        }

        return base.ArrangeOverride(finalSize);

    }

}

Stay in the light!

Robertjan Tuit


Actions

Informations

Leave a comment

You can use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>