読者です 読者をやめる 読者になる 読者になる

がりらぼ

WindowsRuntimeの応援ブログ

WinRT:画像をタイル表示する

WindowsRuntime

WindowsRuntimeではImageコントロールやGridのBackgroundプロパティなど、TileBrushというクラス名ですが画像をタイル表示はできません。

というわけでゴリ押しで画像をタイル表示してみましょう。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

namespace TileImage
{
    public class TileImageCanvas:Canvas
    {


        public Uri TileImageUri
        {
            get { return (Uri)GetValue(TileImageUriProperty); }
            set { SetValue(TileImageUriProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TileImageUri.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TileImageUriProperty =
            DependencyProperty.Register("TileImageUri", typeof(Uri), typeof(TileImageCanvas), new PropertyMetadata(null,(s, e) =>
            {
                TileImageCanvas canvas = s as TileImageCanvas;
                canvas.LoadBitmapImageAsync().ContinueWith(async(param) =>
                {
                    await canvas.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        canvas.UpdateTileImage();
                    });
                    
                });
                
            }));


        BitmapSource _source;
        List<Image> _tileImages;
        public TileImageCanvas()
        {
            _tileImages = new List<Image>();
            
            this.SizeChanged += (s, e) =>
            {
                UpdateTileImage();
            };
            
            
        }

        private async Task LoadBitmapImageAsync()
        {
            _source = new BitmapImage();
            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(TileImageUri);
            IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
            await _source.SetSourceAsync(stream);
        }

        private void UpdateTileImage()
        {
            
            if (_source != null && _source.PixelWidth > 0 && _source.PixelHeight > 0)
            {
                int imgWidth = _source.PixelWidth;
                int imgHeight = _source.PixelHeight;

                foreach (Image i in _tileImages)
                {
                    Children.Remove(i);
                }
                _tileImages.Clear();

                for (int x = 0; x < (ActualWidth + imgWidth); x += imgWidth)
                {
                    for (int y = 0; y < (ActualHeight + imgHeight); y+=imgHeight)
                    {
                        Image img = new Image();
                        img.Source = _source;

                        Canvas.SetLeft(img,x);
                        Canvas.SetTop(img,y);

                        Children.Add(img);
                        _tileImages.Add(img);
                    }
                }

            }
        }
    }
}

Canavsコントロールを継承してImageコントロールをサイズ分だけ配置するという感じです。

あとはPageのxmlnsでTileImage名前空間を指定して、TileImageCanvasクラスをGridの子要素として配置しましょう。

TileImageUriプロパティにはタイル画像へのパスを指定します。

f:id:garicchi:20150107065147p:plain

画像をタイル表示できました。

f:id:garicchi:20150107065342p:plain