使用DependencyProperty将ImageBrush绑定到模板

时间:2011-02-01 10:54:48

标签: silverlight xaml windows-phone-7

我正在尝试创建一个特殊按钮,根据系统中的Foreground颜色为图像着色。解决方案似乎是使用图像作为不透明蒙版来获取颜色,当我像这样直接设置图像时它可以工作:

<Grid>
  <Rectangle x:Name="ImageForeground" Height="48" Width="48" 
    Fill="{StaticResource PhoneForegroundBrush}" >
    <Rectangle.OpacityMask>
      <ImageBrush Stretch="Fill" ImageSource="/icons/play.png"/>
    </Rectangle.OpacityMask>
  </Rectangle>
</Grid>

但是,一旦我尝试使用DependencyProperty为图像精简版创建模板:

public static readonly DependencyProperty ImageProperty  =
  DependencyProperty.Register("Image", typeof(ImageSource), 
                              typeof(RButton), null);  

然后在XAML中这样:

<Grid>
  <Rectangle x:Name="ImageForeground" Height="48" Width="48" 
    Fill="{TemplateBinding Foreground}" >
    <Rectangle.OpacityMask>
      <ImageBrush Stretch="Fill" ImageSource="{TemplateBinding Image}"/>
    </Rectangle.OpacityMask>
  </Rectangle>
</Grid>

我收到错误说:

object of type 'System.Windows.CustomDependencyProperty' 
  cannot be converted to type 'System.Windows.DependencyProperty'

ImageProperty没问题,因为我测试将它绑定到图像而不是像这样

<Image Source="{TemplateBinding Image}" Width="48" Height="48" />

有什么想法吗?我的预感说明了我如何定义我的DependecyProperty,但我不知道如何继续前进。

6 个答案:

答案 0 :(得分:6)

ImageBrush不从FrameworkElement继承,因此它不能是TemplateBound或Data Bound。

答案 1 :(得分:3)

我尝试在基于您给出的XAML的测试项目中复制您的问题,并且不得不承认我没有遇到您描述的问题。如果你能提供RButton的代码和一些关于如何使用控件的上下文,我可能会有更多的运气(或缺少!)。

今天发布了一篇很棒的博文All about Dependency Properties in Silverlight for WP7,您可能会发现它很有用。

更新:我刚刚阅读了完全匹配的article,它完全解释了问题并提供了解决方案。基本上,ImageBrush不是FrameworkElement,因此您无法使用TemplateBinding

答案 2 :(得分:3)

我将它标记为答案虽然不是完整的答案。为了让它全部工作,我不得不做一些调整,因为我无法在TemplateBinding中使用转换器,无论如何叹息......以下代码与Derek指出的article中的转换器一起为我解决了这个问题。

所以要将我的Image DependencyProperty绑定为我的模板中的图像画笔,我必须这样做...

<Grid>
  <Grid.Resources>
    <controls:ImageBrushConverter x:Key="brushConverter"/>
  </Grid.Resources>
  <Rectangle 
    x:Name="ImageForeground"
    Height="48"
    Width="48" 
    Fill="{TemplateBinding Foreground}" 
        DataContext="{TemplateBinding Image}"
        OpacityMask="{Binding Converter={StaticResource brushConverter}}">
  </Rectangle>
</Grid> 

不明显,但它确实有效,这对我来说已经解决了很多。谢谢你的帮助

答案 3 :(得分:2)

您可以使用RelativeSource TemplatedParent绑定而不是TemplateBinding。这基本上是一回事,但它适用于那些模板绑定没有的奇怪情况。

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

答案 4 :(得分:0)

另一种方法,但不需要转换器

<Grid>
<Rectangle x:Name="ImageForeground" DataContext="{TemplateBinding Image}" Height="48" Width="48" 
        Fill="{TemplateBinding Foreground}" >
    <Rectangle.OpacityMask>
        <ImageBrush Stretch="Fill" ImageSource="{Binding DataContext , RelativeSource={RelativeSource AncestorType=Rectangle}}"/>
    </Rectangle.OpacityMask>
</Rectangle>

//或

<Rectangle DataContext="{TemplateBinding IconVisual}" x:Name="Icon" RadiusX="2" RadiusY="2" StrokeThickness="1" Margin="{TemplateBinding Padding}"  Fill="{TemplateBinding Foreground}" Stroke="{TemplateBinding Foreground}" >
                                <Rectangle.OpacityMask>
                                    <VisualBrush Visual="{Binding DataContext , RelativeSource={RelativeSource AncestorType=Rectangle}}"  Stretch="Uniform" />
                                </Rectangle.OpacityMask>
                            </Rectangle>

答案 5 :(得分:0)

或者,如果您是控件的作者,那么OnApplyTemplate,在模板中找到可视画笔并设置其值。

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    VisualBrush oVBrushBack = (VisualBrush)this.Template.FindName("rectVisual", this);

    oVBrushBack.Visual = this.IconVisual;
}