イベントで処理していたのをBindingに変更して
C#と
XAMLの両方で書いてみたけど
どっちがいいのかよくわからん
動作自体は前のときと同じ
Sliderの変更で画像の表示倍率を変更、画面より大きくなったらスクロールバーを表示
配置
Slider 拡大率指定用
ScrollViewer スクロールバー表示用
┗Canvas ImageのScaleに合わせてサイズ変更
┗Image RenderTransformのScaleの変更で拡大
画像の表示倍率のBinding
Target Image.RenderTransform.ScaleTransform.ScaleX or Y
Source Slider.Value
CanvasサイズのBinding
Target Canvas.Width or Height
Source Slider.Value
Converter ValueConverter
ConverterParameter Image.ActualWidth or ActualHeight
CanvasサイズのBindingはMultiBinding
Target Canvas.Width or Height
Source Slider.Value
Source Image.ActualWidth or ActualHeight
Converter MultiValueConverter
<Window x:Class="_20190310_BindingScaleCanvasImage.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:_20190310_BindingScaleCanvasImage"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="500">
<Grid Margin="0,30,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" VerticalAlignment="Center" Background="GhostWhite">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=SliderScale, Path=Value, StringFormat=表示倍率 : 0}" Margin="10 0"/>
<Slider Name="SliderScale" Value="1.0" Minimum="1.0" Maximum="5.0" SmallChange="1.0" LargeChange="1.0"
IsMoveToPointEnabled="False" IsSnapToTickEnabled="True"
Width="100"/>
</StackPanel>
<!--#region 確認用なので不必要-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="Canvas"/>
<TextBlock Text="{Binding ElementName=MyCanvas1,Path=ActualWidth, StringFormat=ActualWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyCanvas1,Path=ActualHeight, StringFormat=ActualHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="ScrollViewer"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ActualWidth, StringFormat=ActualWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ActualHeight, StringFormat=ActualHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ExtentWidth, StringFormat=ExtentWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ExtentHeight, StringFormat=ExtentHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ViewportWidth, StringFormat=ViewportWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ViewportHeight, StringFormat=ViewportHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=HorizontalOffset, StringFormat=HorizontalOffset : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=VerticalOffset, StringFormat=VerticalOffset : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ContentHorizontalOffset, StringFormat=ContentHorizontalOffset : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ContentVerticalOffset, StringFormat=ContentVerticalOffset : 0}" Margin="4,1"/>
</StackPanel>
<!--#endregion-->
</StackPanel>
<ScrollViewer Name="MyScroll1" Grid.Row="1" UseLayoutRounding="True"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Canvas Name="MyCanvas1">
<Image Name="MyImage1" Stretch="None" Canvas.Top="0" Canvas.Left="0"/>
</Canvas>
</ScrollViewer>
</Grid>
</Window>
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace _20190310_BindingScaleCanvasImage
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ContentRendered += MainWindow_ContentRendered;
string filePath1 = @"D:\ブログ用\チェック用2\NEC_6221_2019_02_24_午後わてん_16colors_trim.png";
MyImage1.Source = new BitmapImage(new Uri(filePath1));
}
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
RenderOptions.SetBitmapScalingMode(MyImage1, BitmapScalingMode.NearestNeighbor);
var st = new ScaleTransform();
MyImage1.RenderTransform = st;
var b = new Binding();
b.Source = SliderScale;
b.Path = new PropertyPath(Slider.ValueProperty);
BindingOperations.SetBinding(st, ScaleTransform.ScaleXProperty, b);
BindingOperations.SetBinding(st, ScaleTransform.ScaleYProperty, b);
b = new Binding();
b.Source = SliderScale;
b.Path = new PropertyPath(Slider.ValueProperty);
b.ConverterParameter = MyImage1.ActualWidth;
b.Converter = new MyConverter();
MyCanvas1.SetBinding(WidthProperty, b);
b = new Binding();
b.Source = SliderScale;
b.Path = new PropertyPath(Slider.ValueProperty);
b.ConverterParameter = MyImage1.ActualHeight;
b.Converter = new MyConverter();
MyCanvas1.SetBinding(HeightProperty, b);
}
}
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (double)value * (double)parameter;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
BindingをXAMLで書いたほうのデザイン画面
<Window xClass="_20190310_BindingScaleCanvasImageXAML.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlnsx="http://schemas.microsoft.com/winfx/2006/xaml"
xmlnsd="http://schemas.microsoft.com/expression/blend/2008"
xmlnsmc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlnslocal="clr-namespace:_20190310_BindingScaleCanvasImageXAML"
mcIgnorable="d"
Title="MainWindow" Height="450" Width="800">
<WindowResources>
<localMyMulti xKey="myMultiConverter"/>
</WindowResources>
<Grid Margin="0,30,0,0">
<GridRowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition/>
</GridRowDefinitions>
<StackPanel GridRow="0" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=SliderScale, Path=Value, StringFormat=表示倍率 : 0}" Margin="10 0"/>
<Slider Name="SliderScale" Value="1.0" Minimum="1.0" Maximum="5.0" SmallChange="1.0" LargeChange="1.0"
IsMoveToPointEnabled="False" IsSnapToTickEnabled="True"
Width="100"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="MyCanvas1"/>
<TextBlock Text="{Binding ElementName=MyCanvas1,Path=ActualWidth, StringFormat=ActualWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyCanvas1,Path=ActualHeight, StringFormat=ActualHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="ScrollViewer"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ActualWidth, StringFormat=ActualWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ActualHeight, StringFormat=ActualHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ExtentWidth, StringFormat=ExtentWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ExtentHeight, StringFormat=ExtentHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ViewportWidth, StringFormat=ViewportWidth : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ViewportHeight, StringFormat=ViewportHeight : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=HorizontalOffset, StringFormat=HorizontalOffset : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=VerticalOffset, StringFormat=VerticalOffset : 0}" Margin="4,1"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ContentHorizontalOffset, StringFormat=ContentHorizontalOffset : 0}" Margin="4,1"/>
<TextBlock Text="{Binding ElementName=MyScroll1, Path=ContentVerticalOffset, StringFormat=ContentVerticalOffset : 0}" Margin="4,1"/>
</StackPanel>
</StackPanel>
<ScrollViewer Name="MyScroll1" GridRow="1" UseLayoutRounding="True"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Canvas Name="MyCanvas1" >
<CanvasWidth>
<MultiBinding Converter="{StaticResource myMultiConverter}">
<Binding ElementName="SliderScale" Path="Value"/>
<Binding Path="ActualWidth" ElementName="MyImage1"/>
</MultiBinding>
</CanvasWidth>
<CanvasHeight>
<MultiBinding Converter="{StaticResource myMultiConverter}">
<Binding ElementName="SliderScale" Path="Value"/>
<Binding Path="ActualHeight" ElementName="MyImage1"/>
</MultiBinding>
</CanvasHeight>
<Image Name="MyImage1" Stretch="None" CanvasTop="0" CanvasLeft="0" RenderOptionsBitmapScalingMode="NearestNeighbor">
<ImageRenderTransform>
<ScaleTransform ScaleX="{Binding ElementName=SliderScale, Path=Value}"
ScaleY="{Binding ElementName=SliderScale, Path=Value}">
</ScaleTransform>
</ImageRenderTransform>
</Image>
</Canvas>
</ScrollViewer>
</Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Globalization;
namespace _20190310_BindingScaleCanvasImageXAML
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
string filePath1 = @"D:\ブログ用\チェック用2\NEC_6221_2019_02_24_午後わてん_half.jpg";
MyImage1.Source = new BitmapImage(new Uri(filePath1));
}
}
public class MyMulti : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return (double)values[0] * (double)values[1];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
前回(半年前)はSliderのValueChangedイベント発生時にImageのScaleを変更するコードを
C#で書いていた
これをBindingに変更してみた
Image(画像)の拡大はこれでおk
スクロールバーを画像の拡大に合わせて表示するには、
Canvasのサイズ変更をする必要がある
前回は
SliderのValueChangedイベント発生時に処理を書いていた
これをBindingにしたのが
でソースとなるSlider.
Valueに
Image.ActualWidthを掛けた値
ってことは変換(掛け算)する必要があるので
63~74行目にMyConverter作成
これは引数の
value(ソースの値)に引数のparameterを掛けた値を返すだけのもの
この引数parameterにImage.ActualWidthを渡せばいいので
48行目、BindingのConverterにMyConverterを指定
47行目、Image.ActualWidthをBindingのConverterParameterに指定
C#ではこれでできたので
XAMLで書こうとしたけど書き方がわからなかった
ConverterParameterにMyImage1.ActualWidthを指定する方法がわからない
なので
MultiBindingを使う方法
Slider.Value と Image.ActualWidthの2つをソースにすればいいんじゃないかと
そうすればConverterParameterを使う必要がなくなる
2つのソースの値を掛け算して返すConverter、MyMultiを用意しておいて
これでできた!
できたはできたけどやっぱりめんどくさい気がする
これなら前回のようにイベント発生時に
C#で書いたほうが
ラクかも?
MultiBindingは入力候補が出ない
普通なら
入力候補一覧が表示される、右下
MultiBindingのところだけは入力候補が出ない
参照したところ
ギットハブ
毎回ファイル自体をアップロードして、ただのファイル置き場になっていた
github、少し使い方がわかって同期ボタンで更新できるようになった
関連記事
2年前、2017/6/23