Click here to Skip to main content
Click here to Skip to main content
Go to top

ExImage -- A Silverlight control very similar to the Image control that supports image tiling

, 24 Jan 2010
Rate this:
Please Sign up or sign in to vote.
ExImage is a Silverlight control very similar to the built-in Image control, except it supports three more stretch modes: RepeatX, RepeatY, and RepeatXY, which means images can be tiled horizontally, vertically, or both.

Screen Capture

Introduction

ExImage is a Silverlight control very similar to the built-in Image control, except it supports three more stretch modes: RepeatX, RepeatY and RepeatXY. Which means an image can be tiled in horizontal direction, or vertical direction, or both.

Repeat in X Direction

Image repeat in x direction. The red part is the background.

Repeat in Y Direction

Image repeat in y direction. The red part is the background.

Repeat in both X and Y Direction

Image repeat in both x and y directions.

Background

In HTML, image background supports repeat x, repeat y, and repeat in both directions. But in Silverlight, the Image control only supports None, Fill, Uniform, and UniformFill stretch modes. And, you can't easily tile an image in x/y direction. So, I create the ExImage control to emulate the HTML background image behaviors and lets you easily use it.

Using the Code

It's very similar to the intrinsic Image control both in beahvor and in using the methods. First of all, you should add a reference to the Cokkiy.ExImage assembly to your Silverlight project.

Then, in your page's XAML file, you put it just like an Image control and set its Source and Stretch properties:

<cokkiy:ExImage x:Name="myImage" Source="s.jpg" 
  Stretch="RepeatX" Background="#FFDA2525" Width="400" Height="300"/>

How it Works

We all know that, in Silverlight, the only way to display an image is using the Image control, and there are no methods or functions to directly manipulate the image. So clearly, the only way to tile an image is using many Image controls and tiling them on the destination rectangle. And the end result will be just like tiling the image.

Now, let's look at how the RepeatX mode is implemented.

case ExStretch.RepeatX:
{
     int count = (int)Math.Ceiling(Container.ActualWidth / imgWidth);
     double totalUsedWidth = 0.0; //Already used Width
     double height = Math.Min(imgHeight, Container.ActualHeight);
     for (int i = 0; i < count; i++)
     {
          double remain = Container.ActualWidth - totalUsedWidth;
          Image img = new Image();
          img.Stretch = System.Windows.Media.Stretch.None;
          img.Width = remain >= imgWidth ? imgWidth : remain;
          img.Height = height;
          img.Source = Source;
          Canvas.SetLeft(img, imgWidth * i);
          Canvas.SetTop(img, 0);
          imagesList.Add(img);
          totalUsedWidth += imgWidth;
     }
}
break;

In the code, we first calculate the count, how many Image controls should be put in the x direction. Then, we create as many Image controls and set their left positions. We then save them to a list.

In the end, we add the Images that have been saved in the list to the Conatiner, which is a Canvas.

foreach (var item in imagesList)
{
     Container.Children.Add(item);
}

In the previous code, imgWidth and imgHeight means the real width and height of the image, which can be obtained from the BitmapSource object. The BitmapSource class has two properties, PixelHeight and PixelWidth, which represent the width and height of the image. But those properties only have a value when the image is loaded, so you need to handle the ImageOpened event to retrieve those values.

//Calc image real size
private void CalcImageSize(ImageSource imageSource)
{
    if (imageSource != null)
    {
        Image img = new Image();
        img.ImageOpened += new EventHandler<RoutedEventArgs>(img_ImageOpened);
        img.Source = imageSource;
        Container.Children.Clear();
        // If we don't add this image to the visual tree,
        // the image will never be loaded
        // so, the ImageOpened event will nerver happeded
        Container.Children.Add(img);
    }
}

void img_ImageOpened(object sender, RoutedEventArgs e)
{
    Image img = sender as Image;
    imgHeight = (img.Source as BitmapSource).PixelHeight;
    imgWidth = (img.Source as BitmapSource).PixelWidth;
    Container.Children.Remove(img); // remove this because we no need it
    img = null;
    CreateImage();
}

For more information about how to get the image's dimensions, you may read this Silverlight Tip of the Day #13 - How to Get an Image's Dimensions in Silverlight and these http://forums.silverlight.net/forums/t/14637.aspx articles.

History

  • 24 Jan 2010: Initial post.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

cokkiy
Team Leader
China China
The God created the world.
The programer made the world easy.
I am a programer like c# and c++, so I am writting application with it.
Creating beautiful application make life easy.
If you have a project and looking for a man, I'll be say "hi, I am just the man you are looking for."

Comments and Discussions

 
QuestionHow can we use it as a background? PinmemberYumashin Alex17-Apr-10 23:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141002.1 | Last Updated 24 Jan 2010
Article Copyright 2010 by cokkiy
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid