C# 当目标为ImageBrush.ImageSource时,TemplateBinding失败

C# 当目标为ImageBrush.ImageSource时,TemplateBinding失败,c#,silverlight,xaml,windows-phone,templatebinding,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 readon

为什么在这种特定情况下,
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>
如果我硬编码图像源路径,它也可以正常工作:

            <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>

那么,为什么
TemplateBinding
ImageBrush
中失败呢


更新

通过推断(感谢Chris的回答),可能的因素有:

  • 继承
  • TemplateBinding
    不支持像普通绑定那样的隐式类型转换(即字符串到ImageSource)

我仍然不知道这些点是如何连接的,不过…

这里有一个解决方法。奇怪的是,使用
relativeSourceTemplatedParent
绑定而不是
TemplateBinding
解决了这个问题

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


理论上,这是完全相同的约束。。。那么,谁知道呢?有意思的是,我成功地从你的例子中复制了这种行为,虽然我不能完全确定,但我想我可能理解发生了什么

根据对这个问题的回答:虽然 两种方法实现了几乎相同的目标,但它们在一些关键行为上有所不同。Miroslav Nedyalkov提到的最相关的一个-

“TemplateBindings不允许值转换。它们不允许您 传递转换器,并且不自动将int转换为字符串 示例(这对于绑定来说是正常的)。”

我猜在第二种情况下,绑定将使用内置的WPF转换器将绑定的
字符串
/
URI
转换为
图像源
(指定
图像源
时的通常行为-这就是通常不需要指定绑定转换器的原因)

在第一种情况下,您无法转换默认值,因此无法看到掩码。有趣的是,如果指定了转换器,它是否可以工作


编辑:似乎由于未继承
框架元素

很好的发现-

类型转换问题似乎可以解释这一点,因此可能会有一些额外的复杂性。唯一让我挠头的是为什么
能够绑定。你可能会认为
Image.Source
会失败,原因与
ImageBrush.ImageSource
失败的原因相同——这似乎是一个异常现象。嗯,你说得对——我添加了一个编辑,看起来可能还有其他问题。
<ImageBrush ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Icon}" />