TemplateBinding在目标为ImageBrush.ImageSource时会失败。
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那么,为什么TemplateBinding
在ImageBrush
中失败呢?\n
\n更新\n通过推理(并感谢Chris的答案),可能的因素有:\n
- \n
ImageBrush
从DependencyObject
继承,而不是从FrameworkElement
继承TemplateBinding
不支持隐式类型转换,就像普通绑定那样(即,string-to-ImageSource)
\n
\n
\n虽然我仍然不知道如何连接这些点...
原因:
根据这个问题的答案,TemplateBinding和RelativeSource TemplatedParent两种方法实现了相同的功能,但在某些关键的行为上有所区别。最相关的是Miroslav Nedyalkov提到的问题:“TemplateBindings不允许值转换。它们不允许你传递一个转换器,并且不会自动将int转换为string(这对于绑定来说是正常的)。”
我猜想在第二种情况下,绑定会使用内置的WPF转换器将绑定的string/URI转换为ImageSource(指定ImageSource时的通常行为,这就是为什么通常不需要指定绑定转换器)。
在第一种情况下,由于没有默认的值转换,所以你看不到蒙版。有趣的是,如果指定了一个转换器,它是否能正常工作。
编辑:看起来ImageBrush没有继承自FrameworkElement可能会产生一些额外的复杂性。
解决方法:
这个问题的答案还没有找到,但是可以尝试指定一个转换器来解决这个问题。另外,可能还需要考虑ImageBrush没有继承自FrameworkElement的问题。