Skip to content Skip to sidebar Skip to footer

Reference An Image Imbedded In A WPF Application From Within An HTML File Used As Help Content

I have a WPF desktop application. In it I have a menu option that shows a help window. The help window simply wraps a System.Windows.Controls.WebBrowser control. Now I can create

Solution 1:

Specifying an absolute path to the image will work. For example, in the HTML

<img alt="My Logo" src="file:///C:/Images/MyLogo_3115-2935.jpg" width="500"/>

This solution would not work with an application resource. You would have to create a file locally from the resource, at least temporarily. Or alternatively copy the file locally with the app.

Another, more complex solution would be to embed a webserver into your application, or somewhere else that responds to web request. For more information see HttpListener


Solution 2:

I thank user2509738 for his reply, however, I wanted to use an image that was embedded instead of deploying a separate file. I came up with my own solution and I'll post it here for completeness.

I used the HtmlAgilityPack found at http://htmlagilitypack.codeplex.com to make parsing a little easier.

Here is the HelpWindow.Xaml

<Window x:Class="POC_WpfHelpWindowUsingHtml.HelpWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="HelpWindow" Height="600" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <WebBrowser x:Name="helpBrowser"/>
        <StackPanel x:Name="controlPanel"
                    Grid.Row="1"
                    Orientation="Horizontal"
                    HorizontalAlignment="Right">
            <Button x:Name="closeButton"
                    Margin="0,10,20,10" Width="100"
                    Content="Close"
                    Click="closeButton_Click"/>
        </StackPanel>
    </Grid>
</Window>

Here is the HTML content in the form of a file: HelpContent.html

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <table style="width: 100%;">
        <tr>
            <td>&nbsp;
            </td>
            <td style="align-content:center">
                <img id="imgMyLogo" alt="My Logo" src="Images/MyLogo.png" width="100"/>
            </td>
            <td>&nbsp;</td>
        </tr>
    </table>
</body>
</html>

Here is the HelpWindow.xaml.cs file with most of the magic

using System;
using System.IO;
using System.Windows;
using HtmlAgilityPack;
using System.Reflection;

namespace POC_WpfHelpWindowUsingHtml
{
    /// <summary>
    /// Interaction logic for HelpWindow.xaml
    /// </summary>
    public partial class HelpWindow : Window
    {
        public HelpWindow()
        {
            InitializeComponent();
            Uri uri = new Uri(@"/HelpContent.html", UriKind.Relative);
            System.Windows.Resources.StreamResourceInfo info
                = System.Windows.Application.GetContentStream(uri);
            Stream streamOriginalPage = info.Stream;
            Stream streamModifiedPage = new MemoryStream();
            StreamWriter streamWriter = new StreamWriter(streamModifiedPage);

            // this is from HtmlAgilityPack
            HtmlDocument doc = new HtmlDocument();
            doc.Load(streamOriginalPage);
            // find all the img elements
            foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//img"))
            {
                // change the image reference to an embedded string
                string src = node.GetAttributeValue("src", "");
                src = ConvertImageToEmbeddedString(src);
                if (!string.IsNullOrWhiteSpace(src))
                {
                    node.SetAttributeValue("src", src);
                }
            }
            // save the changes
            doc.Save(streamWriter);
            streamWriter.Flush();
            streamModifiedPage.Position = 0;

            // send the Html content to the WebBrowser component
            helpBrowser.NavigateToStream(streamModifiedPage);
        }

        private void closeButton_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private string ConvertImageToEmbeddedString(string source)
        {
            // find the image type
            string imageType = "png";
            if (source.ToLower().IndexOf("jpg") > -1) imageType = "jpg";
            if (source.ToLower().IndexOf("ico") > -1) imageType = "ico";
            // initialize the return value
            string ret = "";

            if (source.Length > 4)
            {
                if (!source.StartsWith("/"))
                {
                    source = "/" + source;
                }

                // get the embedded image as a stream
                Stream stream = Application.GetResourceStream(
                    new Uri("pack://application:,,," + source)).Stream;
                if (stream != null)
                {
                    // put the image into an Image object
                    System.Drawing.Image image = System.Drawing.Image.FromStream(stream);
                    if (image != null)
                    {
                        // prepend the text for Data URI scheme
                        ret = "data:image/" + imageType + ";base64,";
                        using (MemoryStream ms = new MemoryStream())
                        {
                            // convert the image into a MemoryStream
                            image.Save(ms, image.RawFormat);
                            // convert the image to base64 encoding
                            ret += Convert.ToBase64String(ms.ToArray());
                        }
                    }
                }
            }

            return ret;
        }
    }
}

Post a Comment for "Reference An Image Imbedded In A WPF Application From Within An HTML File Used As Help Content"