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

WPF、ScaleTransformと作成した依存プロパティをBinding

$
0
0

目的は
  • 動的作成で個数も決まっていない対象の拡大縮小
  • 縦横独立と同期をチェックボックスで切り替えできるようにする
  • スライダーやボタンで数値の変更
結果
イメージ 1
OKです



デザイン画面とXAML
ヤフーブログのかんたんモードでXAMLを書くと投稿エラーになるから画像で
イメージ 2


VBコード

Class MainWindow
Private ActBorder As Class1

'バインディング作成用
Private Function GetMyBinding(sObj As DependencyObject, sDp As DependencyProperty, strF As String) As Binding
Dim b As New Binding With {
  .Source = sObj,
  .Path = New PropertyPath(sDp),
  .Mode = BindingMode.TwoWay,
  .StringFormat = strF}
Return b
End Function

'ScaleXとScaleYを同期するチェックボックスをクリックしたとき
Private Sub cbXY_Checked()
If cbXY.IsChecked Then
ActBorder.SetScaleLink(True)
Else
ActBorder.SetScaleLink(False)
End If
End Sub

'アプリ起動時
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
'Border作成してCanvasに追加
ActBorder = New Class1() With {.Width = 30, .Height = 30, .Background = Brushes.Tomato}
MyCanvas.Children.Add(ActBorder)
Canvas.SetLeft(ActBorder, 100)
Canvas.SetTop(ActBorder, 50)

'バインディング設定
'ソース:BorderのScale
'ターゲット:スライダーとテキストブロック
'作成
Dim bindX As Binding = GetMyBinding(ActBorder, Class1.MyScaleXProperty, "ScaleX = {0:0.0}")
Dim bindY As Binding = GetMyBinding(ActBorder, Class1.MyScaleYProperty, "ScaleY = {0:0.0}")
'ターゲットにバインディング
sldXscale.SetBinding(Slider.ValueProperty, bindX)
sldYscale.SetBinding(Slider.ValueProperty, bindY)
tbScaleX.SetBinding(TextBlock.TextProperty, bindX)
tbScaleY.SetBinding(TextBlock.TextProperty, bindY)

'チェックボックスとボタンのクリックイベントと動かす関数を関連付け
AddHandler cbXY.Click, AddressOf cbXY_Checked '同期の有無
AddHandler btXadd.Click, AddressOf ScaleXAdd '拡大
AddHandler btXsub.Click, AddressOf ScaleXSub '縮小
End Sub

Private Sub ScaleXAdd()
ActBorder.MyScaleX += 1
End Sub
Private Sub ScaleXSub()
ActBorder.MyScaleX -= 1
End Sub
End Class



'-----



Public Class Class1
Inherits Border 'Borderクラスをを継承
Private MyScaleTransform As ScaleTransform

'依存関係プロパティ
'ScaleX用
Public Shared ReadOnly Property MyScaleXProperty As DependencyProperty =
DependencyProperty.Register(NameOf(MyScaleX), GetType(Double), GetType(Class1), New PropertyMetadata(1.0))
Public Property MyScaleX As Double
Get
Return GetValue(MyScaleXProperty)
End Get
Set(value As Double)
SetValue(MyScaleXProperty, value)
End Set
End Property

'ScaleY用
Public Shared ReadOnly Property MyScaleYProperty As DependencyProperty =
DependencyProperty.Register(NameOf(MyScaleY), GetType(Double), GetType(Class1), New PropertyMetadata(1.0))
Public Property MyScaleY As Double
Get
Return GetValue(MyScaleYProperty)
End Get
Set(value As Double)
SetValue(MyScaleYProperty, value)
End Set
End Property

'バインディングソースの作成用
Private Function GetMyBinding(sObj As DependencyObject, sDp As DependencyProperty) As Binding
Dim b As New Binding With {
.Source = sObj,
.Path = New PropertyPath(sDp),
.Mode = BindingMode.TwoWay}
Return b
End Function

'コンストラクタ
Public Sub New()
Call Me.New(1.0, 1.0)
End Sub
Public Sub New(sx As Double, sy As Double)
MyScaleX = sx
MyScaleY = sy
'各種トランスフォームをグループにしてRenderTransformに指定
MyScaleTransform = New ScaleTransform '拡縮、今回のメイン
Dim sk As New SkewTransform '並行変形、今回は未使用
Dim ro As New RotateTransform '回転、今回は未使用
'グループ作成
Dim tg As New TransformGroup
With tg.Children
.Add(MyScaleTransform) : .Add(sk) : .Add(ro)
End With
Me.RenderTransform = tg '指定
Me.RenderTransformOrigin = New Point(0.5, 0.5) '変形の基準点は中心

'バインディング
'ソース:用意した依存関係プロパティ
'ターゲット:ScaleTransform
BindingOperations.SetBinding(MyScaleTransform, ScaleTransform.ScaleXProperty, GetMyBinding(Me, MyScaleXProperty))
BindingOperations.SetBinding(MyScaleTransform, ScaleTransform.ScaleYProperty, GetMyBinding(Me, MyScaleYProperty))
End Sub

'ScaleXとScaleYを同期するかしないかの切り替え
Public Sub SetScaleLink(IsLink As Boolean)
If IsLink Then '同期する場合
'Xをソースにして、Yをターゲットにする
BindingOperations.SetBinding(Me, MyScaleYProperty, GetMyBinding(Me, Class1.MyScaleXProperty))

Else '同期しない場合(別々に戻す)
'Yのバインディングを外す(空のBindingをバインディングする)
BindingOperations.SetBinding(Me, MyScaleYProperty, New Binding)
'今の値を継続したいのでXの値をYにコピー、これをしないとYの値が初期値の1になってしまう
MyScaleY = MyScaleX
End If
End Sub
End Class

イメージ 3

この前のRotateTransformのAnglePropertyのバインディングの時とほとんど同じで
違うのは同期するのチェックボックスでバインディングの切り替えをするところ
130~141行目

バインディングの関係
縦横(ScaleXとScaleY)別々のとき
イメージ 5
用意した2つの依存関係プロパティScaleXとScaleYをバインディングソースにして
ScaleTransformのScaleXとScaleYそれぞれにバインディング

X,Yを同期するチェックボックスにチェックを入れたら
バインディングを切り替えて(133行目)、こう
イメージ 4
依存関係プロパティのScaleYを
依存関係プロパティのScaleXにバインディングしただけ
これでYに連なるScaleTransformYとスライダーScaleYもXと同じ値になる



独立と同期の切り替えが難しくていろいろ試して今回の方法になったけどどうかなあ
もっといい方法がありそう


今回のコード





前回の記事
WPF、AnglePropertyと作成した依存プロパティをバインディング ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14979329.html






Viewing all articles
Browse latest Browse all 420

Trending Articles