初歩的なことなのにど忘れしていたのがUserControlに対してBindingする方法。
例えば以下のようなUserControlがあったとします
<Button Content="OK" Width="75" Margin="15 8 15 8" x:Name="ButtonOk"/>
このButtonOkの Commandに対して親WindowからBindingしたい場合。
xaml.csでDependencyPropertyは以下のように追加
public static readonly DependencyProperty OkCommandProperty = DependencyProperty.Register(nameof(OkCommand), typeof(ICommand), typeof(OkPanel)); public ICommand OkCommand { get => (ICommand) GetValue(OkCommandProperty); set => SetValue(OkCommandProperty, value); }
xamlはこのようにして
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:OkPanel}}}"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Button Content="OK" Width="75" Margin="15 8 15 8" x:Name="ButtonOk" Command="{Binding OkCommand}"/> </StackPanel> </Grid>
あとは親Windowから以下のように追加
<controls:OkPanel OkCommand="{Binding OkCommand}"/>
こういうのがパッと出ず、Webを彷徨ってしまうのは私のコードを書く量の少なさに問題があります。(最近気づいた)
もう一つ理由を挙げるとDependencyPropertyのとっつきづらさでしょう。
staticメンバとクラスプロパティの組み合わせでDependencyProperyを用意しますし、DependencyPropertyの宣言はとてつもなく複雑で敬遠してしまいがちです。
もう少しわかりやすいアーキテクチャであって欲しかったですし、WPFの敷居の高さを上げることに繋がっているかなとも感じます。
とはいえ、DependencyPropertyの宣言もnameofや=>などの言語仕様によって大分、かっちり書けるようになっています。
あとは、人がついていけるか。コードを書いて慣れながら理解を深めていくしかないでしょうね。
参考記事
NGケース
UserControlにCommand={Binding OkCommand} などと追加してしまうと、OkCommandを親Windowで指定していないと、Binding Errorが起きてしまって柔軟性に欠けます。
で、私はプログラムでBindingすればいい! とこんなことをしてました。
var okBinding = new Binding(nameof(viewModel.OkCommand))
{
Source = viewModel
};
OkPanel.ButtonOk.SetBinding(Button.CommandProperty, okBinding);