WPFのRelativeSourceのはなし
WPFでバインディングソースを指定するのに使うRelativeSource
.その中で使う「関係」についてよくわかってなかったので,@Posauneさんとこの【WPF】RelativeSource - 亀岡的プログラマ日記で勉強したのを整理がてら書いてみました.
Pro Wpf 4.5 in C#: Windows Presentation Foundation in .net 4.5 (Professional Apress)
- 作者: Matthew MacDonald
- 出版社/メーカー: Apress
- 発売日: 2012/11/21
- メディア: ペーパーバック
- クリック: 1回
- この商品を含むブログを見る
「関係」は以下の4つが指定できるけど,今回はその中でもSelf
とFindAncestor
をコードを書きながら.
- Self
- FindAncestor
- PreviousData
- TemplateParent
Self
Self
は自分自身をソースとして使いたいときに使う.そのクラス自身が持つプロパティをバインドできる.
<Grid Background="Coral"> <StackPanel Margin="20" Background="LightGreen"> <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=HorizontalAlignment}" HorizontalAlignment="Center" Background="Bisque" Margin="10" Padding="15"/> </StackPanel> </Grid>
上記の場合,Textプロパティには自身(つまりTextBlock)のHorizontalAlignment
プロパティをバインドしているため,その値である「Center」が表示される.
他に,例えば,このようにSelf
を指定した状態で Path=Padding
にするとこんな感じになります.
FindAncestor
FindAncestor
は要素をさかのぼって先祖要素をソースとして指定することができる.
このFindAncestor
には以下の2つのオプション?を指定することができる.
- AncestorType
- 参照したい要素の型を指定する.
- AncestorLevel
- 先祖要素を遡ったとき,何番目に見つかった要素を使うかを指定する.
オプションとは書いたけど,AncestorType
は必ず指定する必要がある模様.
一方で,FindAncestor
それ自体は省略可能だったりする.そのせいか,FindAncestorってインテリセンスで出てこないんですよね…まあVS2013使ってると,省略した時に警告を示す下線が出てくることがあって鬱陶しいから書いたらいいんじゃないでしょうか.
<Grid> <StackPanel Background="Coral"> <ContentControl Margin="10" Background="DarkOrchid"> <Border BorderBrush="Aquamarine" BorderThickness="5" Background="Indigo" Margin="10"> <StackPanel Margin="15"> <TextBlock HorizontalAlignment="Center" Background="PaleGreen" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}}, Path=Margin}"/> </StackPanel> </Border> </ContentControl> </StackPanel> </Grid>
上記の例のようにAncestorLevel
を指定しなかった場合には,デフォルトでAncestorLevel = 1
が適用される.
で,以下のコードではAncestorLevel
を明示的に2
を示した場合を示している.
<Grid> <StackPanel Background="Coral" Margin="1"> <ContentControl Margin="10" Background="DarkOrchid"> <Border BorderBrush="Aquamarine" BorderThickness="5" Background="Indigo" Margin="10"> <StackPanel Margin="15"> <TextBlock HorizontalAlignment="Center" Background="PaleGreen" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}, AncestorLevel=2}, Path=Margin}"/> </StackPanel> </Border> </ContentControl> </StackPanel> </Grid>
TextBlockには先祖要素を遡って行き,2番目に現れたStackPanelのMargin
がバインドされていることが確認できる.
おわりに
細かい仕様なんかは未だに理解できたとは言えないけど,ある程度の動きはわかってきたように思います.残りの「関係」についてはまたそのうち……汗
あ,何か間違いありましたらご一報頂けると幸いです.