Question

I'm in WPF and I'm using a WCF service to pull images as base 64 encoded strings. I convert the base 64 encoded strings to ImageSource to assign to Image.Source. I wrote a test app to test the process, and everything seemed to work fine as long as I only used the ImageSource for an Image.Source. But I also need to use some ImageSources for window icons. Here's what I'm trying to do:

ImageSource src = Util.Base64StringToImageSource(tbxBase64String.Text);
//img is a System.Windows.Controls.Image
img.Source = src; //This works just fine
//Class is a Window, so Icon is this.Icon (System.Windows.Window.Icon)
Icon = src; //This throws an InvalidOperationException - "ImageSource for Icon property must be an icon file."

And here's the conversion method:

public static System.Windows.Media.ImageSource Base64StringToImageSource(string base64String)
{
    using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64String)))
    {
        System.Windows.Media.Imaging.BitmapImage bi = new System.Windows.Media.Imaging.BitmapImage();
        bi.BeginInit();
        bi.StreamSource = stream;
        bi.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
        bi.EndInit();
        bi.Freeze();
        return bi;
    }
}

I need to know how to get an ImageSource that can be used for a Window Icon from a base 64 string (or byte array).

Was it helpful?

Solution

I solved it. I dug some more and investigated the exact error that was thrown. Here's the stacktrace:

at System.Windows.Window._OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Window.set_Icon(ImageSource value) at ImageToBase64String.MainWindow.btnStrToImg_Click(Object sender, RoutedEventArgs e) in c:\Data\Source\TorrentRover\TorrentRover\ImageToBase64String\ImageToBase64String\MainWindow.xaml.cs:line 48

You'll notice the exception was thrown in System.Windows.Window._OnIconChanged. Here's what that looks like using ILSpy:

// System.Windows.Window
private static void _OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Window window = (Window)d;
    BitmapFrame bitmapFrame;
    if (e.NewValue == null)
    {
        bitmapFrame = null;
    }
    else
    {
        bitmapFrame = (e.NewValue as BitmapFrame);
        if (bitmapFrame == null)
        {
            throw new InvalidOperationException(SR.Get("IconMustBeBitmapFrame"));
        }
    }
    window.OnIconChanged(bitmapFrame);
}

This led me to believe I need a BitmapFrame around my bitmap image. So I changed my Base64StringToImageSource method, and now it works.

public static System.Windows.Media.ImageSource Base64StringToImageSource(string base64String)
{
    using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64String)))
    {
        return BitmapFrame.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
    }
}

OTHER TIPS

The file has to be a .ico, not a bmp/png/jpg

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top