ClipにX・Y・Width・Heightのプロパティをそれぞれバインドさせたいなぁ、
と思ってもClipプロパティがGeometry型だからそのままはバインドできない。
かといって、new Rect(X, Y, Width, Height)を返すような
Boundsのプロパティを作った上で各プロパティ更新のタイミングで
Boundsのプロパティの更新通知もするようにして…………はめんどい。
というのを、MultiBinding使ったら上手いこと解決できました。
まずX,Y,Width,Heightを受け取ってRectを返すMultiConverterを作ります。
※ Clipとのバインド用として作成したMultiConverterなので、
ConvertBackは使わないかなと思って未実装です。
/// <summary>
/// ClipConverter
/// </summary>
public class ClipConverter : IMultiValueConverter
{
/// <summary>
/// ソース値をバインディング ターゲットの値に変換します。
/// </summary>
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double x = (double)values[0];
double y = (double)values[1];
double width = (double)values[2];
double height = (double)values[3];
return new Rect(x, y, width, height);
}
/// <summary>
/// バインディング ターゲット値をソース値に変換します。
/// </summary>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
そうしたら上記のClipConverterをStaticResourceに定義して、
バインドさせたいコントロールのClipに対して↓のXamlを記述する。
※ Xamlで指定した順番通りに ConvertのValuesに渡ってくるので、
うっかり順番入れ替えたりしないように注意。
<RectangleGeometry>
<RectangleGeometry.Rect>
<MultiBinding Converter="{StaticResource ClipConverter}">
<Binding Path="ClipX" Mode="OneWay"/>
<Binding Path="ClipY" Mode="OneWay"/>
<Binding Path="ClipWidth" Mode="OneWay"/>
<Binding Path="ClipHeight" Mode="OneWay"/>
</MultiBinding>
</RectangleGeometry.Rect>
</RectangleGeometry>
そうすると、ViewModelのClipX、ClipY、ClipWidth、ClipHeightと
コントロールのClipがバインドされた状態になります。
<参考>
Bind Rect Width and Height in xaml (stackoverflow)
MultiBindingの使い方と使いどころ