当目标是 ImageBrush.ImageSource 时 TemplateBinding 失败 [英] TemplateBinding fails when the target is an ImageBrush.ImageSource

查看:30
本文介绍了当目标是 ImageBrush.ImageSource 时 TemplateBinding 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Why does TemplateBinding seems to fail in this specific case?

拿一个基本的扩展按钮:

Take a basic extended button:

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 显示图标:

The control template shows the icon using an 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,则绑定成功:

This fails silently -- the control appears as a solid rectangle. If I use a regular image, instead of the ImageBrush, then the binding is successful:

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

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

It also works correctly if I hard-code the image source path:

            <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 中失败?

So, why does TemplateBinding fail inside an ImageBrush?

更新

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

By deduction (and thanks to the answer from Chris), possible factors are:

  • ImageBrushDependencyObject 而不是从 继承 >FrameworkElement
  • TemplateBinding 不像普通绑定那样支持隐式类型转换(即字符串到图像源)
  • ImageBrush inherits from DependencyObject rather than from FrameworkElement
  • TemplateBinding does not support implicit type conversion in the way that a normal binding does (ie, string-to-ImageSource)

我仍然不明白这些点是如何连接的……

I still don't see how the dots connect, though ...

推荐答案

有趣的是,我设法从您的示例中复制了该行为,虽然我不能完全确定,但我想我可能明白发生了什么.

Interesting, I managed to replicate that behaviour from your example, and although I can't be entirely sure, I think I might understand what's going on.

>

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

Based on the answers to this question: WPF TemplateBinding vs RelativeSource TemplatedParent it seems that although two methods achieve the almost same thing, they differ in some key behaviours. The most relevant one being mentioned by Miroslav Nedyalkov -

"TemplateBindings 不允许值转换.他们不允许你传递一个 Converter 并且不自动将 int 转换为 string示例(这对于绑定来说是正常的)."

"TemplateBindings don't allow value converting. They don't allow you to pass a Converter and don't automatically convert int to string for example (which is normal for a Binding)."

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

I would guess that in the second case, thebinding will use the built in WPF convertor to convert the bound string/URI to an ImageSource (usual behaviour when specifying an ImageSource - it's why you don't usually need to specify a binding convertor).

在第一种情况下,您不会获得默认值转换,因此您将看不到掩码.如果指定了转换器,看看它是否会工作很有趣.

In the first case, you won't get the default value converting, so you won't see the mask. Interesting to see if it would work if a convertor was specified.

看起来 ImageBrush 可能有一些额外的复杂性,而不是从 FrameworkElement 继承:将 ImageBrush 绑定到具有 DependencyProperty 的模板

It looks there might be some additional complications from ImageBrush not inheriting from FrameworkElement: Bind an ImageBrush to a template with a DependencyProperty

这篇关于当目标是 ImageBrush.ImageSource 时 TemplateBinding 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆