読者です 読者をやめる 読者になる 読者になる

うならぼ

どうも。

WPFでウィンドウの位置・サイズをOneWayバインドできない話

C# WPF
<Window x:Class="LivetWPFApplication1.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:vm="clr-namespace:LivetWPFApplication1.ViewModels"

        Left="{Binding Left}" Top="{Binding Top}"
        Width="{Binding Width}" Height="{Binding Height}">
    ...
</Window>


こんな風に書いてみたのだけど上手く反映されない。どうもウィンドウ表示した時点で Binding が消えてしまう。

という話を思い出したので改めて調査してみると、それぞれの依存関係プロパティに Window クラスのあちこちで SetValue している。そういえば OneWay バインディングで値設定しようとするとどうなるんだ??と思ってググったらこれ。

stackoverflow.com

そうなると次の噂にも説明がつく。

「TwoWayならいける」
Bindingを維持したまま値設定できるから
「WidthはMaxWidthとかを代わりに使う」
その辺は前述の自動更新で触られないから

じゃあどうするか。要するに ViewModel から View のプロパティを変更できればいいって話なので色々方法があるのだけど、使い分けがよくわかっていない。

添付プロパティ
元のプロパティと同じようにバインドできる。
Messenger
そもそもプロパティのバインドではなくウィンドウ移動というメッセージとして扱うべきなのでは?というのは思ってた。
Behavior
「ボタンにホバーすると光る」みたいなView側の挙動に使うものという印象。
Trigger
同上。LivetのMessanger使えばいいじゃんって話にもなる。

OneWay版の各プロパティを添付プロパティで作るのがまあ単純で汎用性も高そうだけど、それよりMessenger使った方がまっとうな気がするなあ。

そもそもViewの位置やサイズを動的に変更するってどういう場面かと言うと、デスクトップマスコット的なやつを作ってるって話です。はい。