7

I am having a problem displaying an image with a web URL in a WPF user control. I have worked through all the suggestions for a similar problem asked on this site in Aug 2008 (Image UriSource and Data Binding) but none of those suggestions have worked.

What I'd like to do is:

<Image Width="50" Name="MemberImage">
    <Image.Source>
        <BitmapImage DecodePixelWidth="50" UriSource="{Binding Member.ImageFilePathUri}" />
    </Image.Source>
</Image>

ImageFilePathUri is a Uri created from the string path through:

public Uri ImageFilePathUri
    {
        get
        {
            return new Uri(this.ImageFilePath);
        }
    }
}

This gives the "Property 'UriSource' or property 'StreamSource' must be set." error as expected.

I have also tried using a value converter:

public class ImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var image = new BitmapImage();
        image.BeginInit();
        if (value != null)
        {
            image.UriSource = new Uri((string)value);
        }
        image.DecodePixelWidth = 50;
        image.EndInit();
        return image;
    }
}

However, binding to it using:

<Image Name="TestImage" Width="50" Source="{Binding Path=Member.ImageFilePath, Converter=Parliament.HansardApplicationSuite.Logging.Helpers.ImageConverter}"></Image>

doesn't display the image.

A further attempt to load the image programmatically, in the control constructor and/or the control Loaded event have also not worked:

if (this.MemberRollItemViewModel.Member != null)
{
    var image = new BitmapImage();
    image.BeginInit();
    image.UriSource = new Uri(this.MemberRollItemViewModel.Member.ImageFilePath);
    image.DecodePixelWidth = 50;
    image.EndInit();

    this.MemberImage.Source = image;
}

The one thing that has worked is saving the image to a local file path and displaying that:

<Image Width="50" Name="MemberImage">
    <Image.Source>
        <BitmapImage DecodePixelWidth="50" UriSource="C:\Data\6bc64e7b-2df5-40d5-b6c4-eaf732318222.jpg" />
    </Image.Source>
</Image>

This is obviously only useful in debugging the problem and is not a solution. The same code but substituting the http address for the local file path doesn't work.

<Image.Source>
    <BitmapImage DecodePixelWidth="50" UriSource="http://member.org/6bc64e7b-2df5-40d5-b6c4-eaf732318222.jpg" />
</Image.Source>

Update:

This is the MemberImage property implementation.

public BitmapImage MemberImage
{
    get
    {
        var image = new BitmapImage();

        if (this.Member != null)
        {
            WebRequest request = WebRequest.Create(new Uri(this.Member.ImageFilePath, UriKind.Absolute));
            request.Timeout = -1;
            WebResponse response = request.GetResponse();
            Stream responseStream = response.GetResponseStream();
            BinaryReader reader = new BinaryReader(responseStream);
            MemoryStream memoryStream = new MemoryStream();

            byte[] bytebuffer = new byte[BytesToRead];
            int bytesRead = reader.Read(bytebuffer, 0, BytesToRead);

            while (bytesRead > 0)
            {
                memoryStream.Write(bytebuffer, 0, bytesRead);
                bytesRead = reader.Read(bytebuffer, 0, BytesToRead);
            }

            image.BeginInit();
            memoryStream.Seek(0, SeekOrigin.Begin);

            image.StreamSource = memoryStream;
            image.EndInit();
        }

        return image;
    }
}

Update:

This is how I am binding to the control in my view:

<Image Width="50" Source="{Binding MemberImage}" />

MemberImage is the property I have given above. My data context is being set correctly because that property is being run, it's just not returning an image.

1 Answer 1

13

WebURL can't be provided as a source to UriSource property of BitmapImage. If it is weburl you need to download that image locally and bind that path to UriSource. See the below

http://blogs.windowsclient.net/cennest/archive/2010/03/26/code-for-keeps-wpf-silverlight-retrieve-images-from-db-url.aspx

Update:

void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var image = new BitmapImage();
        int BytesToRead=100;

        WebRequest request = WebRequest.Create(new Uri("http://www.interweb.in/attachments/pc-wallpapers/16187d1222942178-nature-wallpaper-nature-summer-wallpaper.jpg", UriKind.Absolute));
        request.Timeout = -1;
        WebResponse response = request.GetResponse();
        Stream responseStream = response.GetResponseStream();
        BinaryReader reader = new BinaryReader(responseStream);
        MemoryStream memoryStream = new MemoryStream();

        byte[] bytebuffer = new byte[BytesToRead];
        int bytesRead = reader.Read(bytebuffer, 0, BytesToRead);

        while (bytesRead > 0)
        {
            memoryStream.Write(bytebuffer, 0, bytesRead);
            bytesRead = reader.Read(bytebuffer, 0, BytesToRead);
        }

        image.BeginInit();
        memoryStream.Seek(0, SeekOrigin.Begin);

        image.StreamSource = memoryStream;
        image.EndInit();

        myImage.Source = image;
    }
Sign up to request clarification or add additional context in comments.

6 Comments

Rag, thanks for the link. I have tried implementing that by creating a property, MemberImage, returning a BitmapImage using the example in the blog and then binding my Image.Source to that property but it still doesn't display. <Image Width="50" Source="{Binding MemberImage}" /> Does this mean I need to save the image first and then bind to that file path?
No it will just work. Can you post the MemberImage property code?
I have updated my original question with the MemberImage implementation. This still isn't working, just not returning any image.
I tried the same code using Window loaded event. It works fine. Please see the code in my answer. I am thinking problem will be related to your binding to View.
Fixed! It was the network credentials that were missing. Explicitly setting them now works: request.Credentials = CredentialCache.DefaultNetworkCredentials; Thanks for the help!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.