Click here to Skip to main content
15,888,113 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Good Day. I have a user control and I want to create an instance of picture box for each picture that will load simultaneously. The process starts when the form did load, the user control inside the form will appear. Then the user control will read the xml file. It will read and load all the images from a path saved as child node in xml file.

I had started to code the user control:
private void UserControl1_Load(object sender, EventArgs e)
{
   XmlDocument xdoc = new XmlDocument();
   xdoc.Load(@"Items\XMLActiveX.xml");
   XmlNodeList xnl = xdoc.SelectSingleNode("imageroot").ChildNodes;

   label1.Text = String.Empty;

   foreach (XmlNode xNode in xnl) //for each node in xml file
   {
      XmlElement xElem = (XmlElement)xNode;
      XmlNodeList name = xElem.GetElementsByTagName("name");
      XmlNodeList x = xElem.GetElementsByTagName("x");
      XmlNodeList y = xElem.GetElementsByTagName("y");
      XmlNodeList path = xElem.GetElementsByTagName("path");

   for (int i = 0; i < name.Count; i++)
   {
                    
      label1.Text += "Image Name: " + name[i].InnerText + "\n";
      label1.Size += new System.Drawing.Size(100, 10);
      x1 = Convert.ToInt32(x[i].InnerText);
      y1 = Convert.ToInt32(y[i].InnerText);
      label1.Location = new Point(x1, y1);

    }
  }
}

I don't know how to create an instance of several picture box and how to load images. Please help me. Any help will be appreciated. Thanks in advance. :)
Posted
Updated 20-Dec-10 0:19am
v3
Comments
Toniyo Jackson 20-Dec-10 5:20am    
Always write your code inside code block.
Manfred Rudolf Bihy 20-Dec-10 6:20am    
Instead of "" I inserted String.Empty. Double quotes seem to foul up the syntax highlighting.

Hi,

I wrote you a quick example using PictureBox-Controls created on the fly. Just Create a Windows Forms project and replace Program.cs with following snippet.

C#
using System;
using System.Windows.Forms;
using System.Drawing;

namespace DynamicImages
{
    static class Program
    {
        static void Main()
        {
            Application.Run(new TestForm());
        }
    }
    class MyUserControl : Panel
    {
        public MyUserControl()
        {
            AutoScroll = true;
        }
        public void AddImagePictureBox(Image image)
        {
            PictureBox pb = new PictureBox();
            pb.Image = image;
            pb.Dock = DockStyle.Left;
            pb.SizeMode = PictureBoxSizeMode.AutoSize;
            Controls.Add(pb);
        }
    }
    class TestForm : Form
    {
        public TestForm()
        {
            MyUserControl control = new MyUserControl();
            control.Dock = DockStyle.Fill;
            Button buttonAddImage = new Button();
            buttonAddImage.Dock = DockStyle.Bottom;
            buttonAddImage.Text = "Add Image";
            buttonAddImage.Click += delegate(object obj, EventArgs ea)
            {
                // Create dummy image - replace with loading real image
                Random rand = new Random();
                Bitmap bmp = new Bitmap(rand.Next(100, 200), rand.Next(100, 200));
                using (Graphics grfx = Graphics.FromImage(bmp))
                    grfx.FillRectangle(new SolidBrush(Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256))), 0, 0, bmp.Width, bmp.Height);
 
                control.AddImagePictureBox(bmp);
            };
            Controls.Add(control);
            Controls.Add(buttonAddImage);
        }
    }
}

But there is another solution if you OwnerDraw your control, you can just draw the pictures (Graphics.DrawImage) inside the Paint event handler (let me know if you need help
 
Share this answer
 
v2
Comments
Manfred Rudolf Bihy 20-Dec-10 6:16am    
Well done! 5+
yummy02 20-Dec-10 7:23am    
thank s for that. I'll try it tomorrow. Thanks my friend.
yummy02 21-Dec-10 3:43am    
hi johannesnestler, i just want to ask if the code you supply requires a button in loading images, because actually, what I want is to load all images by means of reading the content of xml file. The xml file contains name, x, y, path. Name childnode is the name of the image, then the path childnode is the location of the images. x and y is the location of the images. and there's no button in loading images if possible. Can you help me on that?
johannesnestler 21-Dec-10 12:24pm    
Hi Yummy,

This code is showing how to create Controls in code and add them to a Container. The Button was just for a demo. Replace the Click handler with a method and replace the dummy image with your real image (you read path from xml, than load, then call AddImagePictureBox). Also that my control is derived from Panel was just for a demo, you can do that or you can host a Panel (or other Container-Control) inside your UserControl (or do the manual painting i mentioned).
I made some insertions into your code to help you get the idea of
what you have to do. See my explanation at the end.

C#
private void UserControl1_Load(object sender, EventArgs e)
{
   XmlDocument xdoc = new XmlDocument();
   xdoc.Load(@"Items\XMLActiveX.xml"); //Dont hard code that into the control but rather make it a property of your user control
   XmlNodeList xnl = xdoc.SelectSingleNode("imageroot").ChildNodes;
   label1.Text = String.Empty;
   foreach (XmlNode xNode in xnl) //for each node in xml file
   {
      XmlElement xElem = (XmlElement)xNode;
      XmlNodeList name = xElem.GetElementsByTagName("name");
      XmlNodeList x = xElem.GetElementsByTagName("x");
      XmlNodeList y = xElem.GetElementsByTagName("y");
      XmlNodeList path = xElem.GetElementsByTagName("path");
      // Code saving x[] y[] path[] name[] is missing
      // ...
   }

   for (int i = 0; i < name.Count; i++)
   {
      //If you want to have a label for each picture you'd have to 
      //generate that too dynamically
      label1.Text += "Image Name: " + name[i].InnerText + "\n";
      label1.Size += new System.Drawing.Size(100, 10);
      x1 = Convert.ToInt32(x[i].InnerText);
      y1 = Convert.ToInt32(y[i].InnerText);
      label1.Location = new Point(x1, y1);
      PictureBox pb = new PictureBox();
      Image img = Image.FromFile(path[i]);
      pb.BackgroundImage = img;
      pb.Width = img.Width; //you can choose a fixed size too but then the picturebox would need to stretch or zoom
      // pb.BackgroundImageLayout = ImageLayout.Stretch;
      pb.Height = img.Height;
      //pb.Top = ???  You need to determine how you want to position
      //pb.Left= ???  you picturedox relatively to your label
      //For a different approach see my explanation in the answer
      // You also need to add the PictureBox to the control itself or
      // a container on your control
      // this.Controls.Add(pb);
    }
  }
}


If you want to display the image along with it's name I would suggest that you implement that as a separate user control. It would make your code more structured. Also spreading of the different values into separate arrays is not a good idea.
Make a small class that contains the data you're picking from the XML and you can then use XmlSerialization to extract the data.
You also need to think about screen realestate and how to best use it. If you cant control or know how big pictures can get it's better to go with a fixed size PictureBox and set it to Stretch or Zoom.
If need to add dynamically created controls to a container. That can be your user control itself or a container you have on your user control like a panel for instance.
Instead of using PictureBox's Image property to set the image I used BackgroundImage because it lets you set the ImageLayout in case you need to automatically stretch or zoom.


Regards,


Manfred
 
Share this answer
 
v2
Comments
yummy02 21-Dec-10 2:58am    
by the way, I have some confusion about where to place the code. Should I place the codes inside user control (usercontrol load) or in class library?
Manfred Rudolf Bihy 21-Dec-10 5:38am    
I'm always for separation of concerns, so I would take this course:
Modify your control so it has a method with which you can add instances of a class named PictureInfo (which you need to write yet). In the control you put the code that transforms these PictureInfo instances into the dynamically created display.
When your control is being used later you are still free to decide from what you will build the PictureInfo instances. Right now you are using a file, but at a later time you might choose a DB.
So in order to make your control as independant as possible I'd leave the file parsing and PictureInfo generation out of the control.
That is the way I'd prefer doing it.
Manfred Rudolf Bihy 21-Dec-10 5:44am    
Another jab at this would be to use interfaces. Consider an interface like this:
public interface IPictureInfoProvider
{
List<PictureInfo> GetPictureInfo();
}
In your control you'd have a property named PictureInfoProvider of type IPictureInfoProvider and now you can plugin any kind of IPictureInfoProvider into your control. The control can now fetch the list of PictureInfo instances by calling PictureInfoProvider.GetPictureInfo();
You can implement now a provider for files or for DB or whatever you can come up with and so can others that might want to use your control. It's all about freedom of choice!

Cheers
Here is the snipper.
Image bmp = Image.FromFile(@"C:\myAvatar.png");
PictureBox box = new PictureBox() {
 Image = bmp,
};
 
Share this answer
 
v2
<big>dghnfg</big>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900