WPFでShapeをResourceにして使いまわす
WPFに限らず今時のアプリではアプリ内で使うアイコン等をベクトルデータで持っていることが多いと思います
Illustrator → SVG → XAML
って感じでアイコンデータがやってきたりすると思いますが、これをそのままContentに張り付けるのは悪手ですよね(面倒な時を除く)
ということでアイコンデータはResourceDictionaryに入れて、使うところはKeyを指定するようにしましょう
Resource(App.xaml)
<Application.Resources> <Canvas x:Key="Icon1" x:Shared="False" Width="100" Height="100"> <Ellipse Width="100" Height="100" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}}}"/> </Canvas> <Canvas x:Key="Icon2" x:Shared="False" Width="100" Height="100"> <Rectangle Width="100" Height="100" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}}}"/> </Canvas> </Application.Resources>
MainWindow.xaml
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Button Grid.Row="0" Grid.Column="0" Content="{StaticResource Icon1}"/> <Button Grid.Row="0" Grid.Column="1" Content="{StaticResource Icon1}" Foreground="Blue"/> <Button Grid.Row="1" Grid.Column="0" Content="{StaticResource Icon2}"/> <Button Grid.Row="1" Grid.Column="1" Content="{StaticResource Icon2}" Foreground="Blue"/> </Grid>
結果
ポイント
Shape.Fill
Shape.Fillの指定ですが、ContentControlのForegroundを参照させたい時(Button.Foregroundとか)は上のような感じにしないと参照してくれません
TextBlockとかは何も指定しなければ親のForegroundを見てくれるのでそのつもりでいると???ってなります
上の場合ButtonBaseを継承しているコントロール内でしか効果ありませんが、まぁそれ以外の状況で色を適宜変えたいとかないよね、ね
ということでMainWindow.xamlのGrid.Column="1"にあるボタンではForegroundの指定色にShapeが変更されていることがわかります
x:Shared="False"
ResourceDictionaryに定義しているリソースはデフォルトで使いまわすようになっています(Brushとかそういうのは使いまわした方が効率いいですからね)
ですがCanvasは使いまわしちゃいけないですよね
x:Sharedを書かないとどこか一つにしか出てこなくなります
Buttonの中のContentControlのContentが何かのタイミングで消える
— ぷにお (@vl_o_lv) November 14, 2016
x:Shared="False"とすればそれぞれにインスタンスを作ってくれます
これでかつる!WPFつおい
2016/11/18 追記
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}}}"
より
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ContentControl}}}"
の方がよさそうですね (ButtonBaseをContentControlに変更)