午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

WPF、Borderの背景色(Background.Brush)とスライダーの値を双方向バインディング?

 
目的
MultiBindingとIMultiValueConverterを使って
Borderの背景色(Background.Brush)とスライダーの値を双方向バインディング
イメージ 1
ボタンはBorderの背景色を変更しているだけでスライダーの値には触っていない
 
背景色(Background.Brush)←→スライダー
ボタンで変更
 
期待どおりの動きなんだけど…
 
今回のアプリのダウンロード先
 
デザイン画面
ヤフーブログのかんたんモードでXAMLを書くと投稿エラーになるから画像で

f:id:gogowaten:20191031140911p:plain

 
VBのコード
Imports System.Globalization

'RGB各色の値をSolidColorBrushに変換する
Public Class MyConverterRGB2Brush
    Implements IMultiValueConverter
   'RGB各値を使ってブラシを作って返す
    Public Function Convert(values() As Object,
                            targetType As Type,
                            parameter As Object,
                            culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
       '   Throw New NotImplementedException()
        Dim b As New SolidColorBrush(Color.FromRgb(values(0), values(1), values(2)))
        Return b
    End Function
   'parameterに値を設定したい要素を渡す、今回は各スライダーのあるMainWindow
   'ブラシの色をRGB各値に変換
    Public Function ConvertBack(value As Object,
                                targetTypes() As Type,
                                parameter As Object,
                                culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
       'Throw New NotImplementedException()
        Dim c As MainWindow = parameter
        Dim b As SolidColorBrush = value
       'スライダーに値設定
        c.sldR.Value = b.Color.R
        c.sldG.Value = b.Color.G
        c.sldB.Value = b.Color.B
        Return New Object() {} '空を返している
    End Function
End Class

Class MainWindow

    Private Sub SetSolidColorBrush()
        MyBorder.Background = New SolidColorBrush(Color.FromRgb(255, 180, 50))
    End Sub
    Private Sub SetBrushes()
        MyBorder.Background = Brushes.AliceBlue
    End Sub
    Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
        AddHandler btSetColor1.Click, AddressOf SetSolidColorBrush
        AddHandler btSetColor2.Click, AddressOf SetBrushes

       'RGB各色のスライダーをソースにしてバインディングを作成
        Dim bindR As New Binding With {.Source = sldR, .Path = New PropertyPath(Slider.ValueProperty), .Mode = BindingMode.TwoWay}
        Dim bindG As New Binding With {.Source = sldG, .Path = New PropertyPath(Slider.ValueProperty), .Mode = BindingMode.TwoWay}
        Dim bindB As New Binding With {.Source = sldB, .Path = New PropertyPath(Slider.ValueProperty), .Mode = BindingMode.TwoWay}
       'マルチバインディング作成
        Dim mb As New MultiBinding
        With mb
            .Converter = New MyConverterRGB2Brush
            .Mode = BindingMode.TwoWay
            .ConverterParameter = Me 'これ大事
           '3つのバインディングを詰め込む
            With .Bindings
                .Add(bindR) : .Add(bindG) : .Add(bindB)
            End With
        End With
       'BorderのBackground(Brush)にマルチバインディング
        MyBorder.SetBinding(Border.BackgroundProperty, mb)

        MyBorder.Background = Brushes.Blue
    End Sub
End Class
 
 
背景色の指定はBackgroundPropertyにBrushを指定する
Brushの色はRGB各色で指定するので3つの値が必要
背景色1つに対して3つの値とバインディングするのでMultiBinding(マルチバインディング)する必要がある
マルチバインディングにはMultiValueConverterが必要
 
 
RGBとBrushを相互変換?するMultiValueConverter

f:id:gogowaten:20191031141046p:plain

実際には相互変換していない、できなかった
 
問題なくできたのはRGB3つの値をBrushに変換するConvert(7行目~14行目)
Values()の中には入れた順番に3つの値が入っているから、それを取り出してSolidColorBrushを作成してそれを返している、これはOK
 
 
できなかったのがBrushの色のRGBを取り出して返す方のConvertBack(18行目)、できなかったので空っぽのObjectを返している(何か返さないとエラーっぽくなる)
最初に書いたのが
 

    Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
        Dim b As SolidColorBrush = value
        Dim obj() As Object = New Object() {b.Color.R, b.Color.G, b.Color.B}
        Return obj
    End Function

 
3つの値は返せているはずなんだけどスライダーの値は変化してくれなかったので、今回はConvertBackの引数のparameterを使う方法になった
parameterにMainWindowを入れて渡す
 
イメージ 4
 
MultiBindingのConverterParameterにMe(MainWindow)を入れる(57行目)
これを受け取ったConverterの方では
 
イメージ 5
 
RGBの各スライダーにアクセスできるから直接値を設定している
なのでこれはバインディングじゃない気がするんだよねえ
変な方法になったけど一応動いた感じ
 
 
 
今回のコード全部
 
 
関連記事
前回は3日前
2017/06/20
WPF、ScaleTransformと作成した依存プロパティをBinding ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14981395.html
 
 
次の記事、2017/06/24
WPF、CanvasLeftTopとSliderValueをBinding ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14988621.html
 
2018/04/06は10ヶ月後
カラーピッカーのdll(ライブラリ)作った、WPFユーザーコントロール ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15447603.html
右上のBorderのbackgroundとRGBAの各値をマルチバインディングしている