Reputation: 5055
I have the following XAML that uses a classes CurrencyImg property to look up a static resource at runtime, as there are a lot of these in a treeview, I don't want to have to load the same image 1000 times, I keep it in a resourcedictionary so it is only loaded once.
<Image Name="imgCurrency" Grid.Column="5" Margin="0,0,0,0" Source="{w:ImageStaticResource {Binding CurrencyImg}}" Height="22" VerticalAlignment="Top"/>
With a sample resource dictionary entry as
<ImageSource x:Key="..\Resources\Images\USD.ico">../Resources/Images/USD.ico</ImageSource>
The property is as follows
public string CurrencyImg
{
get
{
if (DisplayUSDRate)
{
return AppString.General.ImagePath + AppString.CurrencyId.USD + ".ico";
}
else
{
return AppString.General.ImagePath + curr + ".ico";
}
}
}
And the property action which does the work
public override bool DisplayUSDRate
{
get { return _customer.DisplayUSDRate; }
set
{
_customer.DisplayUSDRate = value;
OnPropertyChanged("CurrencyImg");
}
}
Now when this runs, the OnPropertyChanged("CurrencyImg") does nothing, and it's clear why. In the XAML I'm not directly binding to the CurrencyImg property, I'm using it as a parameter to my StaticResourceExtension class, so when I call OnPropertyChanged, it thinks there are no bound properties to update, so the XAML image does not update. I can understand this, but obviously this does not help me as what I need to happen is the following.
1) For the class to determine which currency image gets displayed for that row 2) For the images to come from a resource dictionary so they don't get loaded more than once or performance hugely suffers 3) For changes to the DisplayUSDRate property to then reflect by updating the flag to the appropriate image. This is the bit I can't figure out how to do with my StaticResourceExtension (code below)
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);
}
}
}
Upvotes: 1
Views: 299
Reputation: 128060
You could write a very simple binding converter that converts image URI strings to cached ImageSource objects:
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();
}
}
Upvotes: 1