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.
Image repeat in x direction. The red part is the background.
Image repeat in y direction. The red part is the background.
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; 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 Image
s 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.
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();
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); 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.