Created
June 27, 2012 21:05
-
-
Save robfe/3006848 to your computer and use it in GitHub Desktop.
Tilebrush equivalent for WinRT XAML apps.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TileCanvas : Canvas | |
{ | |
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(TileCanvas), new PropertyMetadata(null, ImageSourceChanged)); | |
private Size lastActualSize; | |
public TileCanvas() | |
{ | |
LayoutUpdated += OnLayoutUpdated; | |
} | |
public ImageSource ImageSource | |
{ | |
get { return (ImageSource)GetValue(ImageSourceProperty); } | |
set { SetValue(ImageSourceProperty, value); } | |
} | |
private void OnLayoutUpdated(object sender, object o) | |
{ | |
var newSize = new Size(ActualWidth, ActualHeight); | |
if (lastActualSize != newSize) | |
{ | |
lastActualSize = newSize; | |
Rebuild(); | |
} | |
} | |
private static void ImageSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) | |
{ | |
TileCanvas self = (TileCanvas)o; | |
var src = self.ImageSource; | |
if (src != null) | |
{ | |
var image = new Image { Source = src }; | |
image.ImageOpened += self.ImageOnImageOpened; | |
image.ImageFailed += self.ImageOnImageFailed; | |
//add it to the visual tree to kick off ImageOpened | |
self.Children.Add(image); | |
} | |
} | |
private void ImageOnImageFailed(object sender, ExceptionRoutedEventArgs exceptionRoutedEventArgs) | |
{ | |
var image = (Image)sender; | |
image.ImageOpened -= ImageOnImageOpened; | |
image.ImageFailed -= ImageOnImageFailed; | |
Children.Add(new TextBlock { Text = exceptionRoutedEventArgs.ErrorMessage, Foreground = new SolidColorBrush(Colors.Red) }); | |
} | |
private void ImageOnImageOpened(object sender, RoutedEventArgs routedEventArgs) | |
{ | |
var image = (Image) sender; | |
image.ImageOpened -= ImageOnImageOpened; | |
image.ImageFailed -= ImageOnImageFailed; | |
Rebuild(); | |
} | |
private void Rebuild() | |
{ | |
var bmp = ImageSource as BitmapSource; | |
if (bmp == null) | |
{ | |
return; | |
} | |
var width = bmp.PixelWidth; | |
var height = bmp.PixelHeight; | |
if(width == 0 || height == 0) | |
{ | |
return; | |
} | |
Children.Clear(); | |
for (int x = 0; x < ActualWidth; x += width) | |
{ | |
for (int y = 0; y < ActualHeight; y += height) | |
{ | |
var image = new Image { Source = ImageSource }; | |
Canvas.SetLeft(image, x); | |
Canvas.SetTop(image, y); | |
Children.Add(image); | |
} | |
} | |
Clip = new RectangleGeometry { Rect = new Rect(0, 0, ActualWidth, ActualHeight) }; | |
} | |
} |
To be able to use this in design mode, add a data template into a resource dictionary and load it with a contentpresenter.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
yes it's this mental. An image won't have an accurate width & height until it's raised ImageOpened in winRT, which won't fire till it's added to the visual tree. I've never seen visual artifacts from this approach, but to be safe set a background with a similar tone to the image.
The tiles won't look good if scaled, either.