TemplateBinding在目标为ImageBrush.ImageSource时会失败。

39 浏览
0 Comments

TemplateBinding在目标为ImageBrush.ImageSource时会失败。

为什么在这种特定情况下TemplateBinding似乎失败了?\n以一个基本的扩展按钮为例:\n

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);
    }
}

\n控件模板使用OpacityMask显示图标:\n


\n这会静默失败 - 控件显示为一个实心矩形。如果我使用一个普通的图像,而不是ImageBrush,那么绑定会成功:\n

            
                
                    
                
            

\n如果我硬编码图像源路径,它也可以正常工作:\n

            
                
                    
                        
                            
                        
                    
                
            

\n那么,为什么TemplateBindingImageBrush中失败呢?\n


\n更新\n通过推理(并感谢Chris的答案),可能的因素有:\n

    \n

  • ImageBrushDependencyObject继承,而不是从FrameworkElement继承
  • \n

  • TemplateBinding不支持隐式类型转换,就像普通绑定那样(即,string-to-ImageSource)
  • \n

\n虽然我仍然不知道如何连接这些点...

0
0 Comments

原因:

根据这个问题的答案,TemplateBinding和RelativeSource TemplatedParent两种方法实现了相同的功能,但在某些关键的行为上有所区别。最相关的是Miroslav Nedyalkov提到的问题:“TemplateBindings不允许值转换。它们不允许你传递一个转换器,并且不会自动将int转换为string(这对于绑定来说是正常的)。”

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

在第一种情况下,由于没有默认的值转换,所以你看不到蒙版。有趣的是,如果指定了一个转换器,它是否能正常工作。

编辑:看起来ImageBrush没有继承自FrameworkElement可能会产生一些额外的复杂性。

解决方法:

这个问题的答案还没有找到,但是可以尝试指定一个转换器来解决这个问题。另外,可能还需要考虑ImageBrush没有继承自FrameworkElement的问题。

0
0 Comments

问题的原因是当目标是ImageBrush.ImageSource时,TemplateBinding失效。解决方法是使用RelativeSource TemplatedParent绑定替代TemplateBinding。

以下是解决方法的代码示例:


尽管理论上这两种绑定是完全相同的,但使用RelativeSource TemplatedParent绑定可以解决该问题。

0