So you just took some cool pictures with your brand new digital camera and downloaded them to your computer. Now what? You can use this neat little Virtual Photo Album to help you organize your treasured bits. This album allows you to drag your images directly from Windows Explorer into the spot you want your picture to occupy. You can also edit the captions by clicking on the labels under the pictures. The album data is remembered in an XML database. Also the application allows you to print the current page of the photo album to your printer. Below is the UML representation of the Windows Form class that the virtual photo album uses.
Figure 1 - The UML Design of the Virtual Photo Album(Reverse engineered with WithClass)
This article covers two aspects of .NET used by the Virtual PhotoAlbum
1. How to implement drag-and-drop from Windows Explorer into your form
2. How to use the XML features in .NET exactly like any off the shelf database for reading, writing, filtering, and updating.
Figure 2 - The Virtual Photo Album
Drag and Drop functionality from explorer is fairly easy to implement. In the case of dragging onto the form, you only have to worry about the drop operation since Windows Explorer is already handling the drag operation. First you'll need to set the Windows Form property AllowDrop to true so that the form can accept dropped objects.Then I wired up the DragEnter event to change the cursor to a "copy drop" cursor when the mouse enters the form on a drop.
private void Form1_DragEnter(object sender,System.Windows.Forms.DragEventArgs e)
{
e.Effect = DragDropEffects.Copy; // set the cursor to show a drop copy
}
Next you need to wire up the DragDrop event handler to handle the activities after the mouse drops an object onto the form. The event handler checks that the drop is the DataFormat of FileDrop. If it is a FileDrop type, then it extracts the filename from the DataObject in the DragEvent arguement. It uses the filename to load the image and place it in the picturebox that corresponds to the place where the image was dropped.
private void Form1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string theFile;
try
{
// check to make sure the dropped item is of type FileDrop
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
object filename = e.Data.GetData(DataFormats.FileDrop);
theFile = (string)((System.Array)filename).GetValue(0);
LoadPictureBox(theFile, e.X, e.Y); // Load the image using the path name into the form
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
Using XML like a Database
XML works very nicely with DataSet's which are nothing more than in-memory databases. With this convenient connection between XML and a .NET object you can pretty much perform most necessary database functions in the DataSet and persist them in XML. Below is the code for reading the XML data into a page of the photo album. First the data is read from the XML file into the data set using the ReadXml function. Then the data from the data set is used to populate the graphical page.
void ReadPage()
{
ds.Clear(); // clear out the dataset
// if the album xml database exists, read it in.
if (File.Exists("albumdata.xml"))
{
ds.ReadXml("albumdata.xml");
ReadPageFromDataset(); // read dataset into form
}
PageNumberLabel.Text = (CurrentPage + 1).ToString();
}
ReadPageFromDataSet loops through each of the 4 positions on a page and uses the DataView class to filter out each image row using the Page and Position as selection criteria.
void ReadPageFromDataset()
{
DataTable dt = ds.Tables["Album"];
DataView dv = new DataView(dt);
for (int i = 0; i < 4; i++)
{
// set up a filter to filter out a single row using the Position of the image and the Page Number
dv.RowFilter = "Page = " + CurrentPage.ToString() + " AND Position = " + i.ToString();
if (dv.Count > 0) // check to see if a row exists
{
DataRowView drv = dv[0];
pictures[i].Image = Image.FromFile(drv["ImageName"].ToString());
labels[i].Text = drv["Caption"].ToString();
}
else
{
// clear out image
pictures[i].Image = null;
labels[i].Text = "";
}
}
}
Inserting an image into to the Xml Database is almost as easy. The code below checks the dataset to see if there already exists an image at the row and position we want to insert the image into. If it does, it will update the existing image data, otherwise it will insert a new image data into the xml database, all using the powerful data classes contained in the dataset.
void InsertTheImage(string theFile)
{
// try to find the image row from the Position and Page we are inserting the image into
DataTable dt = ds.Tables["Album"];
DataView dv = new DataView(dt);
dv.RowFilter = "Page = " + CurrentPage.ToString() + " AND Position = " + CurrentPosition.ToString();
// check to see if the row exists
if (dv.Count > 0)
{
// image row exists, update it.
DataRowView drv = dv[0];
object primarykey = drv["ID"];
// update the dataset using the primary key to find the particular row containing the image
DataRow drFound = dt.Rows.Find(new object[]{primarykey});
drFound["ImageName"] = theFile;
drFound["Caption"] = labels[CurrentPosition].Text;
}
else
{
// its a new page and position, insert it into the dataset
DataRow dr = dt.NewRow();
dr["ID"] = dt.Rows.Count;
dr["ImageName"] = theFile;
dr["Position"] = CurrentPosition;
dr["Page"] = CurrentPage;
dr["Caption"] = labels[CurrentPosition].Text;
dt.Rows.Add(dr);
}
// write out the new data to the XML database
ds.WriteXml("albumdata.xml");
}
Conclusion
With .NET, You get some Database capability for free. You can use XML in combination with the dataset to select specific information from an XML data file, sort an XML data file, or even perform calculations on the data in an XML file. As long as a good amount of your database fits in memory, in many cases, this may be the most cost effective way of performing the simple database activity needs of your application.