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的回答),可能的因素有:
- 继承
不支持像普通绑定那样的隐式类型转换(即字符串到ImageSource)TemplateBinding
我仍然不知道这些点是如何连接的,不过…这里有一个解决方法。奇怪的是,使用
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}" />