using images from resources - image control is empty - wpf

I try use images from resources.
I add one png image to resources, name heart.png. It’s public property.
I expose resources with class as advice here:
http://houseofbilz.com/archives/2009/03/15/binding-to-resources-in-silverlightwpf/
Here is class:
namespace Spirit.Util
{
using Properties;
public class PublicResources
{
private readonly static Resources Resources = new Resources();
public Resources SpiritResources { get { return Resources; } }
}
}
I add to app.xaml:
<Util:PublicResources x:Key="SpiritResources"/>
And try use on image control.
<Image Style="{StaticResource InfoIcon}">
<Image.Source>
<!--<MultiBinding Converter="{StaticResource imageToGrayConverter}">-->
<Binding Path="SpiritResources.heart" Source="{StaticResource SpiritResources}"/>
<!--<Binding Path="Oponent.Info.IsFriend" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>-->
</Image.Source>
</Image>
Frist problem is that image control is empty, why?
My complete goal is bind image from resources on image control with multibinding and multiconverter.
If property Isfriend (Oponent.Info.IsFriend) is false I want convert image to grayscale.
Another problem is here. I use this converter class on conversion image to grayscale.
public class ImageToGrayConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
//string imageUri = values[0] as BimapImage;
//value is type of System.Drawing.Image
var image = values[0] as BitmapImage; //new BitmapImage(new Uri(imageUri, UriKind.Relative));
string s = values[1].ToString();
bool isLogged = System.Convert.ToBoolean(s);
if (!isLogged)
{
try
{
if (image != null)
{
var grayBitmapSource = new FormatConvertedBitmap();
grayBitmapSource.BeginInit();
grayBitmapSource.Source = image;
grayBitmapSource.DestinationFormat = PixelFormats.Gray32Float;
grayBitmapSource.EndInit();
return grayBitmapSource;
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
return image;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Value is type of System.Drawing.BitmapImage, I think that I can convert Bitmap to BitmapImage class with this simple class:
http://dog-net.org/content/development/wpf/system-drawing-bitmap-to-bitmapimage/
But I must solve first problem on the beggining. Thank for advice.

As your post is not taggeg as Silverlight, I've solved your problem in WPF application.
I just added existing PNG file to standart Resources. Then put Resources in XAML as static resource and binded PNG file's content to Image element:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:props="clr-namespace:WpfApplication1.Properties">
<Window.Resources>
<self:ImageConverter x:Key="Conv"/>
<props:Resources x:Key="Res"/>
</Window.Resources>
<StackPanel>
<Image Source="{Binding Source={StaticResource Res}, Path=dossier_ardoise_images, Converter={StaticResource Conv}}"/>
</StackPanel>
My converter method looks like this (it's standart IValueConverter, but it doesn't matter):
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is Bitmap)
{
var stream = new MemoryStream();
((Bitmap)value).Save(stream, ImageFormat.Png);
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.EndInit();
return bitmap; // use when you need normal image
var conv = new FormatConvertedBitmap();
conv.BeginInit();
conv.Source = bitmap;
conv.DestinationFormat = PixelFormats.Gray32Float;
conv.EndInit();
return conv; // use when you need grayed image
}
return value;
}
EDITED
In order to get grayscaled bitmap with keeping transparency I would recommend you use next method (from this article):
public static Bitmap MakeGrayscale(Bitmap original)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
//get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);
//create the grayscale ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
//create some image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color matrix attribute
attributes.SetColorMatrix(colorMatrix);
//draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
//dispose the Graphics object
g.Dispose();
return newBitmap;
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is Bitmap)
{
var stream = new MemoryStream();
MakeGrayscale((Bitmap)value).Save(stream, ImageFormat.Png);
//((Bitmap)value).Save(stream, ImageFormat.Png);
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.EndInit();
return bitmap;
}
return value;
}

Related

How to bind image to mahapps icon packs?

How to achieve this either in .XAML or programmatically?
<Image>
<!--<iconPacks:PackIconMaterial Kind="{Binding Status}"/>-->
</Image>
I had same problem.
I am using a package allows only System.Windows.Controls.Image
I solved from C# side.
Lets create a Mahapps Icon
PackIconFontAwesome icon = new PackIconFontAwesome();
icon.Kind = PackIconFontAwesomeKind.AddressBook;
And convert to Geometry
Geometry geo = Geometry.Parse(icon.Data);
GeometryDrawing gd = new GeometryDrawing();
gd.Geometry = geo;
gd.Brush = icon.BorderBrush;
gd.Pen = new Pen(Brushes.White, 100);
icon.Data gives XAML Path of icon Path Markup Syntax
Now we can convert to Image How to: Use a Drawing as an Image Source
DrawingImage geoImage = new DrawingImage(gd);
geoImage.Freeze();
Image img = new Image();
img.Source = geoImage;
Now you can bind where ever you want.
Using a Converter is the easiest way of doing this (expanded on tetralobita's answer) but I didn't see the need to create a bunch of template classes so here is a working version using just one Converter:
namespace MyProject.Converters
{
/// <summary>
/// Converts a <see cref="PackIcon{TKind}" /> to an DrawingImage.
/// Use the ConverterParameter to pass a Brush.
/// </summary>
public class PackIconToImageConverter : IValueConverter
{
/// <summary>
/// Gets or sets the thickness to draw the icon with.
/// </summary>
public double Thickness { get; set; } = 0.25;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
GeometryDrawing geoDrawing = new GeometryDrawing();
geoDrawing.Brush = parameter as Brush ?? Brushes.Black;
geoDrawing.Pen = new Pen(geoDrawing.Brush, Thickness);
if (value is PackIconFontAwesome)
geoDrawing.Geometry = Geometry.Parse((value as PackIcon<PackIconFontAwesomeKind>).Data);
else if (value is PackIconMaterial)
geoDrawing.Geometry = Geometry.Parse((value as PackIcon<PackIconMaterialKind>).Data);
else if (value is PackIconMaterialLight)
geoDrawing.Geometry = Geometry.Parse((value as PackIcon<PackIconEntypoKind>).Data);
else if (value is PackIconModern)
geoDrawing.Geometry = Geometry.Parse((value as PackIcon<PackIconMaterialLightKind>).Data);
else if (value is PackIconEntypo)
geoDrawing.Geometry = Geometry.Parse((value as PackIcon<PackIconEntypoKind>).Data);
else if (value is PackIconOcticons)
geoDrawing.Geometry = Geometry.Parse((value as PackIcon<PackIconOcticonsKind>).Data);
var drawingGroup = new DrawingGroup { Children = { geoDrawing }, Transform = new ScaleTransform(1, -1) };
return new DrawingImage { Drawing = drawingGroup };
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
And then to use the Converter:
Add the Namespace to your .xaml file:
xmlns:converters="clr-namespace:MyProject.Converters"
Then to Display the Icon as an Image:
<Image Source="{Binding Source={icons:PackIconMaterial sitemap},
Converter={converters:PackIconToImageConverter},
ConverterParameter={StaticResource TextBrush}}"/>
Or to use a Dependency Property as in a UserControl or Custom Control add the following to your Control:
/// <summary>
/// Identifies the <see cref="Icon"/> dependency property.
/// </summary>
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(object), typeof(MyControl), new PropertyMetadata(null));
/// <summary>
/// Gets or sets a value that specifies an user specific object which can be used as icon.
/// </summary>
public object Icon {
get { return GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
Then Bind to the Property, in your template add:
<ControlTemplate x:Key="MyControlTemplate" TargetType="{x:Type local:MyControl}">
<Image Source="{TemplateBinding Icon,
Converter={StaticResource IconPackConverter},
ConverterParameter={StaticResource TextBrush}}" />
</ControlTemplate>
Maybe I'm a little too late but I was working on this.
I think that sometimes the solution could be way easier
Create this xmlns on your xaml page:
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
and then...
<Image Source="{Binding Source={iconPacks:BootstrapIconsImage Kind=Upload}}"/>
and the image will show up.
Enjoy coding
Why do you need this in an image? The icons are SVG assets rendered as a font in a custom control. Unless you're trying to do something particularly advanced, you can simply remove the <Image> tags and use the <iconPacks:PackIconMaterial /> control directly as shown here.
There is a better solution which I found it on github, more explanation about the code is here
You can convert it via a converter and use it in XAML like this
ImageSource="{Binding Source={x:Static
iconPacks:PackIconEntypoKind.AddToList}, Converter=
{converters:PackIconEntypoImageSourceConverter}, ConverterParameter=
{StaticResource TextBrush}}"
Converter code is
/// <summary>
/// Converts a <see cref="PackIcon{TKind}" /> to an ImageSource.
/// Use the ConverterParameter to pass a Brush.
/// </summary>
public abstract class PackIconImageSourceConverterBase<TKind> : MarkupExtension, IValueConverter
{
/// <summary>
/// Gets or sets the thickness to draw the icon with.
/// </summary>
public double Thickness { get; set; } = 0.25;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is TKind))
return null;
var foregroundBrush = parameter as Brush ?? Brushes.Black;
return CreateImageSource(value, foregroundBrush, Thickness);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
protected abstract ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness);
}
/// <summary>
/// Converts a <see cref="PackIcon{TKind}" /> to an ImageSource.
/// Use the ConverterParameter to pass a Brush.
/// </summary>
public class PackIconImageSourceConverter : MarkupExtension, IValueConverter
{
/// <summary>
/// Gets or sets the thickness to draw the icon with.
/// </summary>
public double Thickness { get; set; } = 0.25;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is null)
return null;
if (value is PackIconFontAwesomeKind)
return new PackIconFontAwesomeImageSourceConverter { Thickness = Thickness }.Convert(value, targetType, parameter, culture);
if (value is PackIconMaterialKind)
return new PackIconMaterialImageSourceConverter { Thickness = Thickness }.Convert(value, targetType, parameter, culture);
if (value is PackIconMaterialLightKind)
return new PackIconMaterialLightImageSourceConverter { Thickness = Thickness }.Convert(value, targetType, parameter, culture);
if (value is PackIconModernKind)
return new PackIconModernImageSourceConverter { Thickness = Thickness }.Convert(value, targetType, parameter, culture);
if (value is PackIconEntypoKind)
return new PackIconEntypoImageSourceConverter { Thickness = Thickness }.Convert(value, targetType, parameter, culture);
if (value is PackIconOcticonsKind)
return new PackIconOcticonsImageSourceConverter { Thickness = Thickness }.Convert(value, targetType, parameter, culture);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
public class PackIconEntypoImageSourceConverter : PackIconImageSourceConverterBase<PackIconEntypoKind>
{
protected override ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness)
{
var packIcon = new PackIconEntypo { Kind = (PackIconEntypoKind)value };
var geometryDrawing = new GeometryDrawing
{
Geometry = Geometry.Parse(packIcon.Data),
Brush = foregroundBrush,
Pen = new Pen(foregroundBrush, penThickness)
};
var drawingGroup = new DrawingGroup { Children = { geometryDrawing }, Transform = new ScaleTransform(1, -1) };
return new DrawingImage { Drawing = drawingGroup };
}
}
public class PackIconFontAwesomeImageSourceConverter : PackIconImageSourceConverterBase<PackIconFontAwesomeKind>
{
protected override ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness)
{
var packIcon = new PackIconFontAwesome { Kind = (PackIconFontAwesomeKind)value };
var geometryDrawing = new GeometryDrawing
{
Geometry = Geometry.Parse(packIcon.Data),
Brush = foregroundBrush,
Pen = new Pen(foregroundBrush, penThickness)
};
var drawingGroup = new DrawingGroup { Children = { geometryDrawing }, Transform = new ScaleTransform(1, -1) };
return new DrawingImage { Drawing = drawingGroup };
}
}
public class PackIconMaterialImageSourceConverter : PackIconImageSourceConverterBase<PackIconMaterialKind>
{
protected override ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness)
{
var packIcon = new PackIconMaterial { Kind = (PackIconMaterialKind)value };
var geometryDrawing = new GeometryDrawing
{
Geometry = Geometry.Parse(packIcon.Data),
Brush = foregroundBrush,
Pen = new Pen(foregroundBrush, penThickness)
};
var drawingGroup = new DrawingGroup { Children = { geometryDrawing } };
return new DrawingImage { Drawing = drawingGroup };
}
}
public class PackIconMaterialLightImageSourceConverter : PackIconImageSourceConverterBase<PackIconMaterialLightKind>
{
protected override ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness)
{
var packIcon = new PackIconMaterialLight { Kind = (PackIconMaterialLightKind)value };
var geometryDrawing = new GeometryDrawing
{
Geometry = Geometry.Parse(packIcon.Data),
Brush = foregroundBrush,
Pen = new Pen(foregroundBrush, penThickness)
};
var drawingGroup = new DrawingGroup { Children = { geometryDrawing } };
return new DrawingImage { Drawing = drawingGroup };
}
}
public class PackIconModernImageSourceConverter : PackIconImageSourceConverterBase<PackIconModernKind>
{
protected override ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness)
{
var packIcon = new PackIconModern { Kind = (PackIconModernKind)value };
var geometryDrawing = new GeometryDrawing
{
Geometry = Geometry.Parse(packIcon.Data),
Brush = foregroundBrush,
Pen = new Pen(foregroundBrush, penThickness)
};
var drawingGroup = new DrawingGroup { Children = { geometryDrawing } };
return new DrawingImage { Drawing = drawingGroup };
}
}
public class PackIconOcticonsImageSourceConverter : PackIconImageSourceConverterBase<PackIconOcticonsKind>
{
protected override ImageSource CreateImageSource(object value, Brush foregroundBrush, double penThickness)
{
var packIcon = new PackIconOcticons { Kind = (PackIconOcticonsKind)value };
var geometryDrawing = new GeometryDrawing
{
Geometry = Geometry.Parse(packIcon.Data),
Brush = foregroundBrush,
Pen = new Pen(foregroundBrush, penThickness)
};
var drawingGroup = new DrawingGroup { Children = { geometryDrawing } };
return new DrawingImage { Drawing = drawingGroup };
}
}
I have been successfully using the following XAML-only solution:
<ContentControl Margin="10,2" Background="Blue" Foreground="White"
Content="{iconPacks:Material Kind=GestureTap}"
ToolTip="This is a tooltip"
IsEnabled="{Binding ShouldThisBeEnabled}"
Visibility="{Binding ShouldThisBeVisible, Converter={StaticResource VisibilityFromBool}}" />

Calling the Convert method from Converter just once for each item in ItemsControl

I have an ItemsControl control. In its items I show a lot of things: two images in each of the items, some textblocks, etc.
One of the images that are shown in each of the items is the same for all of the items. It's in the Resources.resx file in my project and here's how I load it:
<Image Width="60" Height="60" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2">
<Image.Source>
<Binding Source="{x:Static properties:Resources.myImageName}" Converter="{StaticResource BitmapToImageConverter}" />
</Image.Source>
</Image>
The Convert method of my BitmapToImageConverter converter class looks like this:
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
using (MemoryStream stream = new MemoryStream())
{
((System.Drawing.Bitmap)value).Save(stream, ImageFormat.Png);
stream.Position = 0;
BitmapImage resultImage = new BitmapImage();
resultImage.BeginInit();
resultImage.CacheOption = BitmapCacheOption.OnLoad;
resultImage.StreamSource = stream;
resultImage.EndInit();
resultImage.Freeze();
return resultImage;
}
}
Now, the binding takes a lot of time and I want to shorten it somehow. The Convert method gets called once for every item in my itemscontrol, but with the same image (the same parameters). How can I call it just once for all of the items?
The Converter extends the IValueConverter class.
If I havent misunderstood your question Try this
public class ImageConverter : ValueConverter
{
static BitmapImage resultImage = null;
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (resultImage != null)
return resultImage;
using (MemoryStream stream = new MemoryStream())
{
((System.Drawing.Bitmap)value).Save(stream, ImageFormat.Png);
stream.Position = 0;
resultImage = new BitmapImage();
resultImage.BeginInit();
resultImage.CacheOption = BitmapCacheOption.OnLoad;
resultImage.StreamSource = stream;
resultImage.EndInit();
resultImage.Freeze();
return resultImage;
}
}
Create a static variable and assign it the value first time and return it for next times

Cannot delete file used by some other process

I am displaying some image in my wpf app using following code:
<Image Source="{Binding Path=TemplateImagePath, Mode=TwoWay}" Grid.Row="3" Grid.Column="2" Width="400" Height="200"/>
and setting it's binding property inside code behind's constructor by navigating through some directory, below is the code:
DirectoryInfo Dir = new DirectoryInfo(#"D:/Template");
if (Dir.Exists)
{
if (Dir.GetFiles().Count() > 0)
{
foreach (FileInfo item in Dir.GetFiles())
{
TemplateImagePath = item.FullName;
}
}
}
but if user upload some other image then I need to delete this old image which is I am doing in the following way and setting image binding to null:
DirectoryInfo Dir = new DirectoryInfo(#"D:/Template");
if (Dir.Exists)
{
if (Dir.GetFiles().Count() > 0)
{
foreach (FileInfo item in Dir.GetFiles())
{
TemplateImagePath= null;
File.Delete(item.FullName);
}
}
}
But Iam getting exception that Cannot delete file used by some other process.
How can I delete it?
In order to be able to delete the image while it is displayed in an ImageControl, you have to create a new BitmapImage or BitmapFrame object that has BitmapCacheOption.OnLoad set. The bitmap will then be loaded from file immediately and the file is not locked afterwards.
Change your property from string TemplateImagePath to ImageSource TemplateImage and bind like this:
<Image Source="{Binding TemplateImage}"/>
The set the TemplateImage property like this:
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(item.FullName);
image.EndInit();
TemplateImage = image;
or this:
TemplateImage = BitmapFrame.Create(
new Uri(item.FullName),
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
If you want to keep binding to your TemplateImagePath property you may instead use a binding converter that converts the string to an ImageSource as shown above.
According to Clemens suggestion, here is the binding converter to have a good code-reuse:
namespace Controls
{
[ValueConversion(typeof(String), typeof(ImageSource))]
public class StringToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is string valueString))
{
return null;
}
try
{
ImageSource image = BitmapFrame.Create(new Uri(valueString), BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.OnLoad);
return image;
}
catch { return null; }
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
And there is a string for binding, for example
public string MyImageString { get; set; } = #"C:\test.jpg"
And in the UI the converter is used, in my case from the Library named "Controls"
<Window x:Class="MainFrame"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Controls;assembly=Controls">
<Window.Resources>
<controls:StringToImageSourceConverter x:Key="StringToImageSourceConverter" />
</Window.Resources>
<Grid>
<Image Source="{Binding MyImageString, Converter={StaticResource StringToImageSourceConverter}}" />
</Grid>
</Window>

Sending an EMF file to a specific printer / tray in WPF application

I've got a WPF application that needs to send pre-generated EMF files to a specified printer/tray.
I don't want to show the PrintDialog; the actual printer/tray is configured before hand. I also don't need to actually view the EMF file either; but rather just send it to the printer.
So far, all my R&D into this has led to is a bunch of posts that are 5 years old dealing with EMF and WPF and how it isn't supported.
Has anybody had any luck with this before? Can someone point me in the right direction?
Turns out this was easier than I thought. You can do this via a Image control, and use of a converter. This example takes the file location of the emf file, and puts it into a WPF usercontrol that I then send to a printer.
In XAML:
<Grid Margin="12">
<Image Source="{Binding Path=FileName, Converter={StaticResource emfImageConverter}, Mode=OneWay}"></Image>
</Grid>
and your converter class:
[ValueConversion(typeof(string), typeof(BitmapImage))]
public class EmfImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var fileName = (string)value;
if (fileName == null || !File.Exists(fileName))
return new BitmapImage();
using (var stream = File.Open(fileName, FileMode.Open))
{
return GetImage(stream);
}
}
internal BitmapImage GetImage(Stream fileStream)
{
var img = Image.FromStream(fileStream);
var imgBrush = new BitmapImage { CacheOption = BitmapCacheOption.OnLoad, CreateOptions = BitmapCreateOptions.PreservePixelFormat };
imgBrush.BeginInit();
imgBrush.StreamSource = ConvertImageToMemoryStream(img);
imgBrush.EndInit();
return imgBrush;
}
public MemoryStream ConvertImageToMemoryStream(Image img)
{
var ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Windows Phone 7 Silverlight binding image from the IsolatedStorage

I need to find the way to save images to the IsolatedStorage and show them I the Silverlight (XAML)
Important: Silverlight have to take image “himself”, I cannot set the image from the code behind
I have tried many solutions before.
The very last solution is, to bind byte array and convert them to the Image
XAML
StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<Image Width="110" CacheMode="BitmapCache" Source="{Binding ThumbLocal,Converter={StaticResource imgConverter}}"
Margin="12,0,9,0"/>
<StackPanel Width="311">
Code behind
public byte[] ThumbLocal
{
get;
set;
}
public class ByteImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
MemoryStream memStream = new MemoryStream((byte[])value);
memStream.Seek(0, SeekOrigin.Begin);
BitmapImage thumbLocal = new BitmapImage();
thumbLocal.SetSource(memStream);
return thumbLocal;
}
}
Everything work till I save byte[] to the database and tried to retrieve.
By now I can see the only option save image as file to the IsolatedStorage and then retrieve and covert to byte[].
Is this “smart ” solution?
First, create this converter:
public class BinaryToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is byte[])
{
var bytes = value as byte[];
var stream = new MemoryStream(bytes);
var image = new BitmapImage();
image.SetSource(stream);
stream.Close();
return image;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Second, bind to Your byte[] using this converter, i.e. if you are using MVVM:
View:
<Image Source="{Binding IsolatedStorageImage, Converter={StaticResource BinaryToImageSourceConverter}}" x:Name="ScanImage"/>
You can make property in contrlol (prop snippet) type byte[] and read image to byte array from isostorage, then set value of property to it.
If You got more questions, feel free to ask me.

Resources