Imageコントロールで画像サイズが大きい場合、スクロールバー自動有効化されるカスタムコントロールです。
ScrollViewerとImageを組み合わせれば比較的簡単に実装出来るのでカスタムコントロールにしてみました。
ソースコード
ファイル名:Themes\Generic.xaml
・カスタムコントロールのコントロールテンプレート(構成するコントロール定義)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ScrollableImageSample">
<Style TargetType="{x:Type local:ScrollableImage}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ScrollableImage}">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
CanContentScroll="False"
Focusable="False"
SnapsToDevicePixels="True">
<Image Source="{TemplateBinding Source}"
Stretch="None"
HorizontalAlignment="Left"
VerticalAlignment="Top"
SnapsToDevicePixels="True"/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
ファイル名:Controls\ScrollableImage.cs
・カスタムコントロールの振る舞いの定義
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ScrollableImageSample;
public class ScrollableImage : Control
{
// コンストラクタ
static ScrollableImage()
{
// Generic.xaml の既定テンプレートをこの型に自動適用
DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollableImage),
new FrameworkPropertyMetadata(typeof(ScrollableImage)));
}
/*
依存関係プロパティでSource(ImageSource)を生やす。
*/
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(nameof(Source), typeof(ImageSource), typeof(ScrollableImage),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure));
// ↑AffectsMeasure...Source 変更で必要サイズが変わるため、レイアウト再計測を要求(スクロール有無の再判定にも必要)。
public ImageSource? Source
{
get => (ImageSource?)GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
}
}
ファイル名:MainWindow.xaml
・カスタムコントロールを使う側のコード
<Window x:Class="ScrollableImageSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ScrollableImageSample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:ScrollableImage Source="H:\csharp\wpf\ScrollableImageSample\memo.jpg" />
</Grid>
</Window>
実行イメージ
自動的にスクロールバーが表示される。
感想
カスタムコントロールのコントロールテンプレートは Generic.xaml に定義(内容は ScrollViewer+Image)。
csコード側でテンプレート部品を触らない場合は、必要な依存プロパティだけ TemplateBinding で接続すればOK。
コメント