@Grabacr07さんの素敵な記事!
WinRTでやるときはこうだよっていうのをちょっとだけ。主にScrollViewerがいけてない部分を補足するだけです。ScrollViewerのScrollChangedイベントはWinRTにはないので、ViewChangedイベントと、LayoutUpdatedイベントを組み合わせて同じような動きを再現させます。コード的には以下のような感じ。
private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { this.UpdateViewportSize(); } private void ScrollViewer_LayoutUpdated(object sender, object e) { this.UpdateViewportSize(); } private void UpdateViewportSize() { var xfactor = this.Thumbnail.ActualWidth / this.ScrollViewer.ExtentWidth; var yfactor = this.Thumbnail.ActualHeight / this.ScrollViewer.ExtentHeight; var left = this.ScrollViewer.HorizontalOffset * xfactor; var top = this.ScrollViewer.VerticalOffset * yfactor; var width = this.ScrollViewer.ViewportWidth * xfactor; if (width > this.Thumbnail.ActualWidth) { width = this.Thumbnail.ActualWidth; } var height = this.ScrollViewer.ViewportHeight * yfactor; if (height > this.Thumbnail.ActualHeight) { height = this.Thumbnail.ActualHeight; } Canvas.SetTop(this.Viewport, top); Canvas.SetLeft(this.Viewport, left); this.Viewport.Width = width; this.Viewport.Height = height; }
これだけで、WinRTでも動くようになります。(試したのはWin10TPのUAPだけどたぶん大丈夫でしょう…)
コード
一応XAMLとC#のコードをはっておきます。
<Page x:Class="App24.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App24" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition/> </Grid.ColumnDefinitions> <Canvas Margin="10" Width="{Binding Path=ActualWidth, ElementName=Thumbnail}" Height="{Binding Path=ActualHeight, ElementName=Thumbnail}" HorizontalAlignment="Center"> <Image x:Name="Thumbnail" Width="100" Stretch="Uniform" Source="ms-appx:///Assets/tree.jpg" /> <Thumb x:Name="Viewport" DragDelta="Viewport_DragDelta"> <Thumb.Template> <ControlTemplate TargetType="Thumb"> <Border BorderThickness="2" BorderBrush="Red" Background="Transparent" /> </ControlTemplate> </Thumb.Template> </Thumb> </Canvas> <ScrollViewer x:Name="ScrollViewer" Grid.Column="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" ViewChanged="ScrollViewer_ViewChanged" LayoutUpdated="ScrollViewer_LayoutUpdated"> <Image Source="ms-appx:///Assets/tree.jpg" /> </ScrollViewer> </Grid> </Page>
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 namespace App24 { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { this.UpdateViewportSize(); } private void ScrollViewer_LayoutUpdated(object sender, object e) { this.UpdateViewportSize(); } private void UpdateViewportSize() { var xfactor = this.Thumbnail.ActualWidth / this.ScrollViewer.ExtentWidth; var yfactor = this.Thumbnail.ActualHeight / this.ScrollViewer.ExtentHeight; var left = this.ScrollViewer.HorizontalOffset * xfactor; var top = this.ScrollViewer.VerticalOffset * yfactor; var width = this.ScrollViewer.ViewportWidth * xfactor; if (width > this.Thumbnail.ActualWidth) { width = this.Thumbnail.ActualWidth; } var height = this.ScrollViewer.ViewportHeight * yfactor; if (height > this.Thumbnail.ActualHeight) { height = this.Thumbnail.ActualHeight; } Canvas.SetTop(this.Viewport, top); Canvas.SetLeft(this.Viewport, left); this.Viewport.Width = width; this.Viewport.Height = height; } private void Viewport_DragDelta(object sender, DragDeltaEventArgs e) { this.ScrollViewer.ScrollToHorizontalOffset( this.ScrollViewer.HorizontalOffset + (e.HorizontalChange * this.ScrollViewer.ExtentWidth / this.Viewport.ActualWidth)); this.ScrollViewer.ScrollToVerticalOffset( this.ScrollViewer.VerticalOffset + (e.VerticalChange * this.ScrollViewer.ExtentHeight / this.Viewport.ActualHeight)); } } }