イベントで処理していたのをBindingに変更してC#とXAMLの両方で書いてみたけど
どっちがいいのかよくわからん
Sliderの変更で画像の表示倍率を変更、画面より大きくなったらスクロールバーを表示
配置
Slider拡大率指定用
ScrollViewerスクロールバー表示用
┗CanvasImageのScaleに合わせてサイズ変更
┗ImageRenderTransformのScaleの変更で拡大
C#で書いたほう
画像の表示倍率のBinding
TargetImage.RenderTransform.ScaleTransform.ScaleX or Y
SourceSlider.Value
CanvasサイズのBinding
TargetCanvas.Width or Height
SourceSlider.Value
ConverterValueConverter
ConverterParameterImage.ActualWidth or ActualHeight
XAMLで書いたほう
画像の表示倍率のBindingはC#と同じ
CanvasサイズのBindingはMultiBinding
TargetCanvas.Width or Height
SourceSlider.Value
SourceImage.ActualWidth or ActualHeight
ConverterMultiValueConverter
BindingをC#で書いたほうのデザイン画面
C#
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";
//Imageに画像表示
MyImage1.Source = new BitmapImage(new Uri(filePath1));
}
//アプリが表示された直後
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
//Image拡大表示の補間法指定、今回はニアレストネイバー法
RenderOptions.SetBitmapScalingMode(MyImage1, BitmapScalingMode.NearestNeighbor);
//ScaleTransform作成してImageのRenderTransformに指定
//これをしないと拡大できない
var st = new ScaleTransform();
MyImage1.RenderTransform = st;
//ここからBinding
//ソース SliderのValue
//ターゲット ImageのScaleTransformのXとY
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);
//ソース Slider.Value
//ターゲット CanvasのWidth
//Canvas.Width = Slider.Value * Image.ActualWidthをにするためにConverter指定
//ParameterにImage.Width
b = new Binding();
b.Source = SliderScale;
b.Path = new PropertyPath(Slider.ValueProperty);
b.ConverterParameter = MyImage1.ActualWidth;
b.Converter = new MyConverter();
MyCanvas1.SetBinding(WidthProperty, b);
//↑のHeight版
b = new Binding();
b.Source = SliderScale;
b.Path = new PropertyPath(Slider.ValueProperty);
b.ConverterParameter = MyImage1.ActualHeight;
b.Converter = new MyConverter();
MyCanvas1.SetBinding(HeightProperty, b);
}
}
//Value * parameterを返す
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で書いたほうのデザイン画面
C#
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";
//Imageに画像表示
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のサイズ変更
スクロールバーを画像の拡大に合わせて表示するには、Canvasのサイズ変更をする必要がある
前回は
これをBindingにしたのが
Canvas.Widthとして欲しい値は
Canvas.Width = Slider.Value * Image.ActualWidth
でソースとなる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を用意しておいて
XAMLで使えるようにしておいて
これでできた!
できたはできたけどやっぱりめんどくさい気がする
これなら前回のようにイベント発生時にC#で書いたほうがラクかも?
MultiBindingは入力候補が出ない
普通なら
入力候補一覧が表示される、右下
MultiBindingのところだけは入力候補が出ない
間違っているんじゃないかって不安になる
参照したところ
c# - Multibinding generates "Cannot set MultiBinding because MultiValueConverter must be specified" - Stack Overflow
https://stackoverflow.com/questions/19510196/multibinding-generates-cannot-set-multibinding-because-multivalueconverter-must
ギットハブ
BindingをC#で書いたほう
XAMLで書いたほう
毎回ファイル自体をアップロードして、ただのファイル置き場になっていたgithub、少し使い方がわかって同期ボタンで更新できるようになった
最初にリポジトリをgithubに作って、それをVisual Studioから複製すればよかったのね
関連記事
半年前、2018/11/15
WPF、スクロールバーの同期、2つの画像を並べて拡大して見比べたい、ScrollViewer ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15754500.html
2年前、2017/6/23
WPF、Borderの背景色(Background.Brush)とスライダーの値を双方向バインディング? ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14987741.html