現在、押された状態と通常の状態の背景としてユーザー提供の画像を使用する単純なカスタムボタンに取り組んでいます。ボタンがたくさんあるので、カスタムボタンを作成して、押された状態と通常の状態の画像に2つのプロパティを実装することにしました。
これが私が使っているコードです
public partial class ThemeableButton : Button
{
public ThemeableButton()
{
InitializeComponent();
}
public static readonly DependencyProperty PressedContentBackgroundSourceProperty = DependencyProperty.Register(
"PressedContentBackgroundSource", typeof(ImageSource), typeof(ThemeableButton), null);
public ImageSource PressedContentBackgroundSource
{
get { return (ImageSource)GetValue(PressedContentBackgroundSourceProperty); }
set
{
(value as BitmapImage).CreateOptions = BitmapCreateOptions.BackgroundCreation;
SetValue(PressedContentBackgroundSourceProperty, value);
}
}
public static readonly DependencyProperty NormalContentBackgroundSourceProperty =
DependencyProperty.Register("NormalContentBackgroundSource", typeof(ImageSource), typeof(ThemeableButton), null);
public ImageSource NormalContentBackgroundSource
{
get { return (ImageSource)GetValue(NormalContentBackgroundSourceProperty); }
set
{
(value as BitmapImage).CreateOptions = BitmapCreateOptions.BackgroundCreation;
SetValue(NormalContentBackgroundSourceProperty, value);
}
}
}
このボタンのスタイルは次のように書きました
<Style x:Key="ThemeableButtonTemplate" TargetType="MJbox_UIComponents_Controls:ThemeableButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MJbox_UIComponents_Controls:ThemeableButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{TemplateBinding NormalContentBackgroundSource}">
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{TemplateBinding PressedContentBackgroundSource}">
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0">
<Image x:Name="ButtonBackground" Stretch="None" Source="{TemplateBinding NormalContentBackgroundSource}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
簡単な例を試してみました
<Controls:ThemeableButton Style="{StaticResource ThemeableButtonTemplate}" x:Name="btnDidntNeedIt" NormalContentBackgroundSource="{Binding Source={StaticResource DefaultTheme}, Path=DidntHaveButtonUnselected}"
PressedContentBackgroundSource="{Binding Source={StaticResource DefaultTheme}, Path=DidntHaveButtonSelected}"
/>
しかし、画像が表示されないので、スタイルからTemplateBindingを削除して、画像ファイルの相対ソースに置き換えてみましたが、正常に機能しました。アプリのボタンごとにカスタマイズされたスタイルを作成したくありません。考えられる回避策はありますか?
以前にこれに遭遇しましたが、TemplateBindingはコントロールのカスタム依存関係プロパティでは機能しません。これらの関連する質問を参照してください。
テンプレートのバインドとカスタムコンポーネントのバインドに関する問題
TemplateBindingが特定の場合に機能しない(TranslateTransformを使用する場合)
私はいつも代わりにこれを使用しました:
{Binding MyProperty, RelativeSource={RelativeSource TemplatedParent}}
これは意味的にはTemplateBindingと同じであり、値コンバーターなどもサポートできます...