Quantcast
Channel: 午後わてんのブログ
Viewing all articles
Browse latest Browse all 420

以前イベントで処理していたのをBindingにしてC#とXAMLで書いてみた

$
0
0
イベントで処理していたのをBindingに変更してC#とXAMLの両方で書いてみたけど
どっちがいいのかよくわからん
イメージ 1
動作自体は前のときと同じ
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#で書いたほうのデザイン画面
イメージ 12

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で書いたほうのデザイン画面
イメージ 13


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に変更してみた
イメージ 2

XAMLで書くとこうで、C#で書くと↓

イメージ 3
この場合はC#よりXAMLで書いたほうがラクかも

Image(画像)の拡大はこれでおk


Canvasのサイズ変更
スクロールバーを画像の拡大に合わせて表示するには、Canvasのサイズ変更をする必要がある
前回は
イメージ 4
SliderのValueChangedイベント発生時に処理を書いていた
これをBindingにしたのが

イメージ 5
これは逆にめんどくさくなった気がする

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を指定する方法がわからない
イメージ 6

なので
MultiBindingを使う方法
Slider.Value と Image.ActualWidthの2つをソースにすればいいんじゃないかと
そうすればConverterParameterを使う必要がなくなる

2つのソースの値を掛け算して返すConverter、MyMultiを用意しておいて
イメージ 8

XAMLで使えるようにしておいて
イメージ 9

イメージ 7
これでできた!
できたはできたけどやっぱりめんどくさい気がする
これなら前回のようにイベント発生時にC#で書いたほうがラクかも?


MultiBindingは入力候補が出ない
普通なら
イメージ 11
ElementNameを入力しているところ
入力候補一覧が表示される、右下

MultiBindingのところだけは入力候補が出ない
イメージ 10
間違っているんじゃないかって不安になる


参照したところ
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
MultiBindingをVBで書いてる、結構いろいろ試していたんだなあ、あんまり憶えていない




Viewing all articles
Browse latest Browse all 420

Trending Articles