【问题标题】:Why is find anchestor binding to attached property not working via value converter?为什么 find anchestor 绑定到附加属性不能通过值转换器工作?
【发布时间】:2015-10-19 11:04:14
【问题描述】:

我有一个包含矢量图形图标的资源字典。附加属性允许我定义图标的颜色。当我将图标用作静态资源时,从资源字典到附加到图像的颜色的绑定正在工作。但是当我使用带有值转换器的绑定时,颜色绑定不起作用。

有人知道为什么吗?

这里是用法示例:

<!-- OK, smile is green -->
<Image Source="{StaticResource MaterialMood}" svg:Image.Brush="Green" />

<!-- Not OK, simle is black -->
<Image Source="{Binding Image,Converter={StaticResource GoogleMaterialSource}}" svg:Image.Brush="Green" />

ResourceDictionary.xaml:

<DrawingImage x:Key="MaterialMood" x:Shared="False">
  <DrawingImage.Drawing>
     <DrawingGroup>
        <DrawingGroup>
           <DrawingGroup.ClipGeometry>
              <RectangleGeometry Rect="0,0,24,24" />
           </DrawingGroup.ClipGeometry>
           <GeometryDrawing Brush="{Binding Path=(svg:Image.Brush),RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Image}},FallbackValue=Black}">
              <GeometryDrawing.Geometry>
                 <PathGeometry FillRule="Nonzero" Figures="M11.99,2C6.47,2 2,6.48 2,12 2,17.52 6.47,22 11.99,22 17.52,22 22,17.52 22,12 22,6.48 17.52,2 11.99,2z M12,20C7.58,20 4,16.42 4,12 4,7.58 7.58,4 12,4 16.42,4 20,7.58 20,12 20,16.42 16.42,20 12,20z M15.5,11C16.33,11 17,10.33 17,9.5 17,8.67 16.33,8 15.5,8 14.67,8 14,8.67 14,9.5 14,10.33 14.67,11 15.5,11z M8.5,11C9.33,11 10,10.33 10,9.5 10,8.67 9.33,8 8.5,8 7.67,8 7,8.67 7,9.5 7,10.33 7.67,11 8.5,11z M12,17.5C14.33,17.5,16.31,16.04,17.11,14L6.89,14C7.69,16.04,9.67,17.5,12,17.5z" />
              </GeometryDrawing.Geometry>
           </GeometryDrawing>
        </DrawingGroup>
     </DrawingGroup>
  </DrawingImage.Drawing>
</DrawingImage>

C#:

public enum MaterialImage
{
  Mood
}

public class GoogleMaterialSourceConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
     if (value == null) return null;

     var imageName = string.Format("Material{0}", value);
     if (!Application.Current.Resources.Contains(imageName)) return null;

     var image = Application.Current.Resources[imageName] as DrawingImage;
     return image == null ? null : image.Clone(); // `x:Shared = false;` ???
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
     throw new NotImplementedException();
  }
}

public static class Image
{
  public static readonly DependencyProperty BrushProperty = DependencyProperty.RegisterAttached(
     "Brush",
     typeof(Brush),
     typeof(Image),
     new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Inherits));

  [TypeConverter(typeof(BrushConverter))]
  public static Brush GetBrush(DependencyObject element)
  {
     return (Brush)element.GetValue(Image.BrushProperty);
  }

  [TypeConverter(typeof(BrushConverter))]
  public static void SetBrush(DependencyObject element, Brush value)
  {
     element.SetValue(Image.BrushProperty, value);
  }
}

public partial class MainWindow : Window
{
  public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image",
     typeof (MaterialImage), typeof (MainWindow), new PropertyMetadata(MaterialImage.Mood));

  public MaterialImage Image
  {
     get { return (MaterialImage)this.GetValue(MainWindow.ImageProperty); }
     set { this.SetValue(MainWindow.ImageProperty, value); }
  }

  public MainWindow()
  {
     this.DataContext = this;
     this.InitializeComponent();
  }
}

【问题讨论】:

  • 我想知道附加属性Image.Brush 在这里是如何工作的。它没有什么特别之处,目前它只能在一个 DependencyObject 上存储一个 Brush 的值。但这还不足以使用所需/指定的画笔在Source 中绘制图像源。
  • Image.Brush 只是颜色的一种“后备存储”。它不必画任何东西。图标的画笔通过 FindAnchestor 绑定从那里获取颜色。
  • Image 属性在哪里?是怎么暴露的。 (提示 1 )您是否有任何绑定错误(提示 2)
  • Imge 属性位于主窗口 (DependencyProperty.Register) 的代码隐藏中,并且它正在工作,数据上下文是正确的。静态资源没有绑定错误。使用 IValueConverter 的绑定有一个绑定错误:'Cannot find source for binding with reference RelativeSource FindAncestor, AncestorType='System.Windows.Controls.Image', AncestorLevel='1''. BindingExpression:Path=(0); DataItem=null; target element is 'GeometryDrawing' (HashCode=37895910); target property is 'Brush' (type 'Brush')
  • 此代码Application.Current.Resources[imageName] 表示您将DrawingImage 放在应用程序的资源中。当然,在视觉树上方不会找到任何图像控件。之前的代码有效,因为您将DrawingImage 放在Image.Resources 或某些内部元素的资源中,因此Binding 可以成功找到图像。

标签: c# wpf xaml binding


【解决方案1】:

感谢 King King 的评论,我能够更改代码,使其现在可以工作。 现在使用另一个附加属性来设置图像源,而不是使用 IValueConverter 绑定到枚举值:

XAML:

<Image svg:Image.Brush="Green" svg:Image.Source="{Binding Image}" />

CS:

public static class Image
{
  // color stuff goes here
  ... 

  public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached("Source", typeof(MaterialImage), typeof(Image), new FrameworkPropertyMetadata(MaterialImage.Mood, OnSourceChangedCallback));

  public static MaterialImage GetSource(DependencyObject element) { return (MaterialImage)element.GetValue(Image.SourceProperty); }
  public static void SetSource(DependencyObject element, MaterialImage value) { element.SetValue(Image.SourceProperty, value); }

  private static void OnSourceChangedCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
  {
     var image = (System.Windows.Controls.Image)source;
     if (args.NewValue == null)
     {
        image.Source = null;
        return;
     }

     var resourceName = string.Format("Material{0}", args.NewValue);
     if (!Application.Current.Resources.Contains(resourceName))
     {
        image.Source = null;
        return;
     }

     image.Source = Application.Current.Resources[resourceName] as DrawingImage;
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2016-06-23
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多