0

My main goal is to load an image from a server and while the loading process is running I would like to show a placeholder instead of the real image.

For reaching this goal I am using C# and Windows Forms. I have to use the proxy pattern and C# background worker which means the loading and the view are using different threads.

I know there are already examples of using proxy pattern for image loading but I have not found any solution which uses a background worker for loading images from a server.

I have already implemented the core functionality but I am now stucking at the question: When the image is fully loaded and therefore the background worker has done his job, how can I force my picture box to load the real image.

My design looks like this:

public class MyPictureBox : PictureBox
{
    AbstractImage myImage;

    public MyPictureBox(AbstractImage image) : base()
    {
        this.myImage = image;
    }
}

public abstract class AbstractImage
{
    protected readonly String url;

    public AbstractImage(String url)
    {
        this.url = url;
    }

    public abstract Image getImage();
}

public class RealImage : AbstractImage
{
    private Image img;

    public RealImage(String url) : base(url)
    {

    }

    public override Image getImage()
    {
        if (img == null)
        {
            WebRequest requestPic = WebRequest.Create(url);
            WebResponse responsePic = requestPic.GetResponse();
            img = Image.FromStream(responsePic.GetResponseStream());
        }
        return img;
    }
}

public class ProxyImage : AbstractImage
{
    private readonly Image Dummy = Image.FromFile("Waiting.jpg");
    private readonly RealImage realImage;
    public readonly BackgroundWorker bgw;
    private bool done = false;

    public ProxyImage(String url) : base(url)
    {
        realImage = new RealImage(url);
        bgw = new BackgroundWorker();
        bgw.WorkerReportsProgress = true;
        bgw.DoWork += new DoWorkEventHandler(loadImage);
        bgw.RunWorkerAsync();
    }

    public void loadImage(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Loading file" + url);
        realImage.getImage();
        Console.WriteLine("Finished loading file " + url);
        done = true;
        bgw.ReportProgress(100);
    }

    public override Image getImage()
    {
        return done ? realImage.getImage() : Dummy;
    }
}

public partial class Form1 : Form
{
    private String urlPrefix = "http://...";
    String[] filenames = { "Penguins.jpg", "Koala.jpg", "Desert.jpg"};

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        ProxyImage image = new ProxyImage(urlPrefix + filenames[0]);
        MyPictureBox pb = new MyPictureBox(image);
        pb.Image = image.getImage();
        pb.SizeMode = PictureBoxSizeMode.Zoom;
        pb.Size = new Size(200, 200);
        pb.Location = new Point(0, 0);
        Controls.Add(pb);
    }
}

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

At the moment the picture box only shows the dummy image because the background worker has loaded the image but doesn't inform the picture box to use this instead of the dummy image.

I would be glad if anyone could tell my how to set the real image as image of the picture box.

Michael Andorfer
  • 1,660
  • 5
  • 25
  • 45
  • ProxyImage should raise an event when loading is done. You subscribe to the event and update the picture box image in the event handler – Jesús López Nov 14 '15 at 10:38
  • What you are doing is already provided out of the box by `PictureBox` control via `InitialImage` property and `LoadAsync` method – Ivan Stoev Nov 14 '15 at 10:53
  • @IvanStoev Yes, I know but I have to do this as an assignment for university so that we aim the ability to write such functionalities by ourselves. – Michael Andorfer Nov 14 '15 at 11:12

0 Answers0