なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

WPF で Binding 後に解決されたクラスとプロパティを取得したい

WPF で XAML 側に DataContext や ViewModel を代入した後、実際に Binding で解決された結果を使いたいケースがある (ほんとうに?)。 そういうときに使うテク。

例えば以下のような XAML があったとき:

<Page
    x:Class="Starist.Views.Pages.TagPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:Starist.Views.Pages"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="TagPage"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid>
        <TextBlock Text="{Binding ViewModel.Name, Mode=OneWay}" />
    </Grid>
</Page>

コードビハインド側から、 ViewModel.Name が、どこの誰?というのを知りたい場合、以下のようにすると得られる。

var expression = this.GetBindingExpression(TextBlock.TextProperty);
expression.ResolvedSource // => TagPageViewModel
expression.ResolvedSourcePropertyName // => "Name"

あとは、例えば INotifyPropertyChanged などのようなもので購読することで Binding を再現することもできる:

var expression = this.GetBindingExpression(TextBlock.TextProperty);
if (expression.ResolvedSource is INotifyPropertyChanged c)
{
    c.PropertyChanged += (_, e) => {
        if (e.PropertyName == expression.ResolvedSourcePropertyName)
        {
            Debug.WriteLine("Woo!");
        }
    }
}

という小ネタでした。