【WPF】親からの比率でいろいろ指定したい、Data Binding, Prism, Reactive

ずーっと何年もこのブログのアクセスランキングTOP5は全部C#の記事なんですぉ。
ということでたまにはC#だぉ。


はい、表題の通り。例えば親の幅の半分の幅にしたいとかいうことあるよね。
Gridとかならさあれだけどさ。Canvas想定ね、Canvas
親のActualWidthを取ってこないとだめなケースの場合に使えるかと?VMでそんなもん持ちたくないやん?

はい、いつも通りおもむろに以下のクラスを作りましょう。OneWay前提なのでConvertBackは適当。

using System;
using System.Globalization;
using System.Windows.Data;

namespace Hoge.Converter
{
    public sealed class RatioConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            => (double)values[0] * (double)values[1];

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            => null;
    }
}

で、VM

using Prism.Mvvm;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;

namespace Hoge.Controls
{
    /// <summary>
    /// View model for HogeControl
    /// </summary>
    public sealed partial class HogeControlVM:  BindableBase
    {
        public ReadOnlyReactiveProperty<double> WidthRatioProperty { get; }
        private double Width { get => width; set => SetProperty(ref width, value); }
        private double width;
    }

    public partial class HogeControlVM
    {
        public HogeControlVM()
        {
            WidthRatioProperty = this.ObserveProperty(x => x.Width).ToReadOnlyReactiveProperty();
            Width = 0.5;
        }
    }
}



コードビハインドは省略で、View

<UserControl x:Class="Hoge.Controls.HogeControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:c="clr-namespace:Hoge.Converter"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <c:RatioConverter x:Key="Ratio" />
    </UserControl.Resources>
    <Canvas Name="Canvas">
        <TextBox Text="Hogeeee">
            <TextBox.Width>
                <MultiBinding Converter="{StaticResource Ratio}">
                    <Binding ElementName="Canvas" Path="Width" />
                    <Binding Path="WidthRatioProperty.Value" />
                </MultiBinding>
            </TextBox.Width>
        </TextBox>
    </Canvas>
</UserControl>

IDE使わずに書いてるから動かなかったらごめんちゃい?