【问题标题】:TemplateBinding to DependencyProperty on a custom control not working自定义控件上的 TemplateBinding 到 DependencyProperty 不起作用
【发布时间】:2011-12-28 13:47:35
【问题描述】:

目前,我正在开发一个简单的自定义按钮,该按钮使用用户提供的图像作为按下状态和正常状态的背景。我有很多按钮,所以我决定编写一个自定义按钮,并为按下和正常状态的图片实现两个属性。

这是我正在使用的代码

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 并将其替换为图像文件的相对源,它工作正常。我只是不想为应用程序上的每个按钮创建自定义样式。任何可能的解决方法?

【问题讨论】:

    标签: c# silverlight xaml windows-phone-7


    【解决方案1】:

    我之前遇到过,TemplateBinding 不适用于控件上的自定义依赖属性。请参阅以下相关问题:

    issues with template binding and binding of custom component

    TemplateBinding does not work in certain cases(when using TranslateTransform)

    我一直用这个代替:

    {Binding MyProperty, RelativeSource={RelativeSource TemplatedParent}}
    

    与TemplateBinding语义相同,也可以支持值转换器等...

    【讨论】:

    • 这也是对我有用的答案。我希望 TemplateBinding 能够正常工作,并消除一些神秘和随意性。
    • "...TemplateBinding 不适用于控件上的自定义依赖属性[.]" 它适用于我。我的自定义控件的ControlTemplate 中的&lt;Rectangle Fill="{TemplateBinding FillBrush}" /&gt; 用我的FillBrush 自定义依赖属性填充Rectangle,甚至在VS 的属性表中显示该属性并用我在设计时设置的任何内容填充它。也许这是自 2011 年以来的新事物?无论如何,它现在工作正常。 (但要注意动画不是Freezeables。你仍然不能这样做。)
    • 更具体地说(冒着 SO 的机器人抱怨我在 cmets 中进行扩展讨论的风险),TemplateBinding 将不适用于 Freezeables 的属性。据我所知,它默默地失败了。您的解决方案当然适用于这些情况。
    • 这似乎不适用于 .net 4.7.2。他们堵住了这个漏洞吗?
    猜你喜欢
    • 2021-05-09
    • 2020-09-01
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多