2012-11-02 87 views
1

我有以下XAML使用類CurrencyImg屬性在運行時查找靜態資源,因爲有很多這些在樹視圖中,我不想要加載相同的圖像1000次,我把它保存在一個resourcedictionary中,所以它只加載一次。DependencyProperty not firing

<Image Name="imgCurrency" Grid.Column="5" Margin="0,0,0,0" Source="{w:ImageStaticResource {Binding CurrencyImg}}" Height="22" VerticalAlignment="Top"/> 

與樣本資源字典條目

<ImageSource x:Key="..\Resources\Images\USD.ico">../Resources/Images/USD.ico</ImageSource> 

性能爲如下

public string CurrencyImg 
{ 
    get 
    { 
     if (DisplayUSDRate) 
     { 
      return AppString.General.ImagePath + AppString.CurrencyId.USD + ".ico"; 
     } 
     else 
     { 
      return AppString.General.ImagePath + curr + ".ico"; 
     } 
    } 
} 

和物業作用,這做的工作

public override bool DisplayUSDRate 
{ 
    get { return _customer.DisplayUSDRate; } 
    set 
    { 
     _customer.DisplayUSDRate = value; 
     OnPropertyChanged("CurrencyImg"); 
    } 
} 

現在,當這運行, OnPropertyChanged(「CurrencyImg」)什麼也不做,這很明顯。在XAML中,我沒有直接綁定到CurrencyImg屬性,我使用它作爲我的StaticResourceExtension類的參數,所以當我調用OnPropertyChanged時,它認爲沒有綁定的屬性需要更新,所以XAML圖像不會更新。我可以理解這一點,但顯然這並不能幫助我,因爲我需要發生的是以下幾點。

1)類,以確定哪些貨幣形象得到顯示該行 2)對於圖像來自一個資源字典,以便它們不會超過一次或性能受到巨大的3 加載更多)變動到DisplayUSDRate屬性,然後通過將標誌更新爲適當的圖像來進行反映。這是我無法弄清楚如何與我的StaticResourceExtension(下面的代碼)

using System; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Markup; 

namespace Citi.Rbcs.UI.Windows 
{ 
    public class ImageStaticResource : StaticResourceExtension 
    { 
     public Binding Binding { get; set; } 
     private static readonly DependencyProperty DummyProperty; 

     public ImageStaticResource() 
     { 
     } 

     public ImageStaticResource(Binding binding) 
     { 
      Binding = binding; 
     } 

     static ImageStaticResource() 
     { 
      DummyProperty = DependencyProperty.RegisterAttached(
       "Dummy", 
       typeof (Object), 
       typeof (DependencyObject), 
       new UIPropertyMetadata(null)); 
     } 

     public override object ProvideValue(IServiceProvider serviceProvider) 
     { 
      var target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); 
      var targetObject = (FrameworkElement)target.TargetObject; 

      Binding.Source = targetObject.DataContext; 
      var DummyDO = new DependencyObject(); 
      BindingOperations.SetBinding(DummyDO, DummyProperty, Binding); 

      ResourceKey = DummyDO.GetValue(DummyProperty); 

      var resourceDictionary = new ResourceDictionary 
             { 
              Source = new Uri("pack://application:,,,/Windows/Images.xaml") 
             }; 

      var key = (string) ResourceKey;    
      if (!resourceDictionary.Contains(key)) ResourceKey = "Default"; 

      return base.ProvideValue(serviceProvider); 
     } 
    } 
} 
+0

這看起來不太複雜。爲什麼不直接寫一個[CurrencyImg]字符串轉換爲ImageSource的[綁定轉換器](http://msdn.microsoft.com/en-us/library/system.windows.data.binding.converter.aspx) 。無論如何,位圖圖像由WPF緩存。如果你不依賴這種緩存,你可能會在轉換器中實現你自己的緩存機制。 – Clemens

+0

直接使用字符串作爲源綁定絕對不會緩存它,就像我這樣做,例如它需要永久加載樹視圖控件,1000行中的每一行在treeview中似乎正在加載它自己的圖像版本。如果我用BindingConverter做它,它會以不同的方式對待它嗎?我同意StaticResource的查找是非常糟糕和複雜的,所以如果有另一種方式來做到這一點,我會喜歡它。它的速度非常慢,按照我以前的方式進行,並使用靜態資源字典進行操作,使其非常快速 – NZJames

+0

如果您編寫了轉換器,則可以在其中實現您自己的緩存機制。使用例如[MemoryCache](http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx),圖像URL作爲關鍵字,ImageSource(BitmapImage)作爲緩存值。 – Clemens

回答

1

你可以寫一個非常簡單的binding converter該圖像URI字符串轉換爲緩存ImageSource的對象做位:

public class StringToImageConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var imageUrl = value as string; 
     var image = MemoryCache.Default.Get(imageUrl) as ImageSource; 

     if (image == null) 
     { 
      image = new BitmapImage(new Uri(imageUrl)); 
      MemoryCache.Default.Set(imageUrl, image, new CacheItemPolicy()); 
     } 

     return image; 
    } 

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