4

为什么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>

那么,为什么TemplateBinding在一个内部失败ImageBrush


更新

通过推断(并且感谢克里斯的回答),可能的因素是:

我仍然没有看到这些点是如何连接的,虽然......

4

2 回答 2

4

这是一种解决方法。奇怪的是,使用RelativeSource TemplatedParent绑定而不是TemplateBinding解决问题。

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

从理论上讲,这是完全相同的绑定……所以,谁知道呢?什么都行。

于 2014-03-02T22:23:30.423 回答
1

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

根据这个问题的答案:WPF TemplateBinding vs RelativeSource TemplatedParent似乎虽然两种方法实现了几乎相同的东西,但它们在一些关键行为上有所不同。Miroslav Nedyalkov 提到的最相关的一个 -

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

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

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

编辑:看起来可能有一些额外的并发症ImageBrush不继承自FrameworkElementBind an ImageBrush to a template with a DependencyProperty

于 2014-03-02T23:00:24.430 回答