当目标是ImageBrush.ImageSource时,TemplateBinding失败

时间:2014-03-02 22:11:44

标签: c# silverlight xaml windows-phone templatebinding

为什么TemplateBinding在这种特定情况下似乎失败了?

采用基本的扩展按钮:

public class IconButton : Button
{
    public ImageSource Icon
    {
        get { return (ImageSource)GetValue(IconProperty); }
        set { SetValue(IconProperty, value); }
    }
    public static readonly DependencyProperty ImageProperty =
        DependencyProperty.Register("Icon", typeof(ImageSource), typeof(IconButton), new PropertyMetadata(null));

    public IconButton()
    {
        DefaultStyleKey = typeof(IconButton);
    }
}

控件模板使用OpacityMask

显示图标
<Style TargetType="controls:IconButton">
    <Setter Property="Width" Value="30" />
    <Setter Property="Height" Value="30" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:IconButton">
                <Grid>
                    <Rectangle Fill="{StaticResource PhoneForegroundBrush}"
                               Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                        <Rectangle.OpacityMask>
                            <ImageBrush ImageSource="{TemplateBinding Icon}" />
                        </Rectangle.OpacityMask>
                    </Rectangle>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

无声地失败 - 控件显示为实心矩形。如果我使用常规图像而不是ImageBrush,则绑定成功:

            <ControlTemplate TargetType="controls:IconButton">
                <Grid>
                    <Image Source="{TemplateBinding Icon}" />
                </Grid>
            </ControlTemplate>

如果我对图像源路径进行硬编码,它也能正常工作:

            <ControlTemplate TargetType="controls:IconButton">
                <Grid>
                    <Rectangle Fill="{StaticResource PhoneForegroundBrush}"
                               Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                        <Rectangle.OpacityMask>
                            <ImageBrush ImageSource="/Images/appbar.next.rest.png" />
                        </Rectangle.OpacityMask>
                    </Rectangle>
                </Grid>
            </ControlTemplate>

那么,为什么TemplateBindingImageBrush内失败?


更新

通过演绎(并且得益于Chris的答案),可能的因素是:

我仍然看不到点如何连接,但是......

2 个答案:

答案 0 :(得分:4)

这是一种解决方法。奇怪的是,使用RelativeSource TemplatedParent绑定代替TemplateBinding修复了问题。

<ImageBrush ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Icon}" />

从理论上讲,这是完全相同的约束......所以,谁知道呢?无论什么都有效。

答案 1 :(得分:1)

有趣的是,我设法从你的例子中复制了这种行为,虽然我不能完全确定,但我想我可能会理解发生了什么。

基于这个问题的答案:WPF TemplateBinding vs RelativeSource TemplatedParent似乎虽然如此 两种方法几乎完全相同,它们在一些关键行为上有所不同。 Miroslav Nedyalkov提到的最相关的一个 -

  

“TemplateBindings不允许进行价值转换。他们不允许你   传递一个转换器,不要自动将int转换为字符串   例子(绑定是正常的)。“

我猜想在第二种情况下,绑定将使用内置的WPF转换器将绑定的string / URI转换为ImageSource(指定{{}时的常规行为1}} - 这就是你通常不需要指定绑定转换器的原因。)

在第一种情况下,您将无法获得默认值转换,因此您将看不到遮罩。有趣的是,如果指定了转换器,它是否会起作用。

编辑:ImageSource未继承ImageBrush FrameworkElement可能会出现一些其他并发症:Bind an ImageBrush to a template with a DependencyProperty