-
-
Save aloisdg/a743d7113a0189afec4b to your computer and use it in GitHub Desktop.
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) | |
return; | |
_lastActualSize = newSize; | |
Rebuild(); | |
} | |
private static void ImageSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) | |
{ | |
var self = (TileCanvas)o; | |
var src = self.ImageSource; | |
if (src == null) return; | |
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) | |
{ | |
ManageImageEvent((Image)sender); | |
Children.Add(new TextBlock | |
{ | |
Text = exceptionRoutedEventArgs.ErrorException.Message, | |
Foreground = new SolidColorBrush(Colors.Red) | |
}); | |
} | |
private void ImageOnImageOpened(object sender, RoutedEventArgs routedEventArgs) | |
{ | |
ManageImageEvent((Image)sender); | |
Children.Clear(); | |
Rebuild(); | |
} | |
private void ManageImageEvent(Image image) | |
{ | |
image.ImageOpened -= ImageOnImageOpened; | |
image.ImageFailed -= ImageOnImageFailed; | |
} | |
private void Rebuild() | |
{ | |
var bmp = ImageSource as BitmapSource; | |
if (bmp == null | |
|| bmp.PixelWidth == 0 || bmp.PixelHeight == 0 | |
|| ActualWidth.Equals(0) || ActualHeight.Equals(0)) | |
return; | |
double currentTiledWidth = -1; | |
double currentTiledHeight = -1; | |
foreach (var child in Children.Where(c => c is Image).Cast<Image>()) | |
{ | |
var childTop = GetTop(child); | |
var childLeft = GetLeft(child); | |
if (childLeft >= ActualWidth || childTop >= ActualHeight) | |
Children.Remove(child); | |
else | |
{ | |
currentTiledWidth = Math.Max(childLeft, currentTiledWidth); | |
currentTiledHeight = Math.Max(childTop, currentTiledHeight); | |
} | |
} | |
for (var x = 0; x < ActualWidth; x += bmp.PixelWidth) | |
for (var y = 0; y < ActualHeight; y += bmp.PixelHeight) | |
if (x > currentTiledWidth || y > currentTiledHeight) | |
{ | |
var image = new Image { Source = ImageSource }; | |
SetLeft(image, x); | |
SetTop(image, y); | |
Children.Add(image); | |
} | |
Clip = new RectangleGeometry { Rect = new Rect(0, 0, ActualWidth, ActualHeight) }; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment