Meet us at PRINT 19. Chicago, IL. Oct. 3 - 5.
This documentation is for the old version. Go to the latest Graphics Mill docs

Using the ThumbnailListView Control as a File Browser

The ThumbnailListView control is ideal for such task as creating a file browser similar to Windows Explorer. This topic describes how it can be done.

About PIDL

To accomplish this task, the ThumbnailListItem class will be used to represent file system objects: files, folders, drives, and so on. These items are based on a special object called PIDL.

PIDL stands for pointer to an item identifier list. It can be interpreted as an element of a tree-structured hierarchy of the shell namespace. This hierarchy includes such objects as:

  • Drives
  • Folders
  • Files
  • Virtual objects, like My Documents folder, Control Panel, Network Printers, and so on

As any tree-like structure, the shell namespace always has a root element called Desktop. Each PIDL stores references to its children and parent PIDLs (if available). This allows to navigate the tree.

In Graphics Mill for .NET, PIDL objects are represented by the Aurigma.GraphicsMill.WinControls.Pidl class. This class has a number of members which allows to navigate the shell namespace, get path to file/folder (if available), and even grab file content.

Each ThumbnailListItem stores a PIDL which can be accessed using the ThumbnailListItem.Pidl property.

Preparing Application GUI

Now, you can create a file browser application. This application will provide the following functionality:

  • It will display files, folders, and other elements of the current folder.
  • When the folder is clicked, the user will navigate into this folder.
  • When the user clicks an image file, the image will be loaded in the BitmapViewer control.
  • The user will be able to navigate to the top or parent folder.
  • The user will be able to switch between views.

To implement such application, create a new Windows Forms application and add the following controls:

  • One ThumbnailListView control
  • One BitmapViewer control
  • One System.Windows.Forms.ComboBox control for switching between view modes.
  • Two System.Windows.Forms.Button controls for navigating to the parent and top folders.
  • System.Windows.Forms.Label controls to give the user an idea about the purpose of each control.

After that configure columns for details view as discussed in the Setting Up the Details View topic.

The result will look as follows:

File Browser application design
Fig. 1. File Browser application design

Managing Items in Thumbnail List

The first thing you need to implement is displaying objects of the current folder in the ThumbnailListView control. Every time the user navigates to some folder, all previously displayed items should be removed, and new items should be loaded.

Define a method which will display subitems of a given PIDL.

Visual Basic
' Parent PIDL (necessary for the Up button)
Private _parentPidl As Aurigma.GraphicsMill.WinControls.Pidl

Private Sub JumpToPidl(ByVal pidl As Aurigma.GraphicsMill.WinControls.Pidl)

    ' Clear all previously displayed items.
    thumbnailListView1.Items.Clear()

    ' If pidl is null, it means that we intend to display the root item.
    ' Otherwise we extract all children and display them.
    If Not pidl Is Nothing Then

        ' We need to keep the parent PIDL to be able to implement ability
        ' to navigate one level up.
        _parentPidl = pidl.Parent

        ' Add all children to the control.
        Dim subPidl As Aurigma.GraphicsMill.WinControls.Pidl
        For Each subPidl In pidl.Items

            thumbnailListView1.Items.Add( _
             New Aurigma.GraphicsMill.WinControls.ThumbnailListItem(subPidl))
        Next
    Else
        ' Root item has no parent.
        _parentPidl = Nothing

        ' Add the root item.
        thumbnailListView1.Items.Add( _
         New Aurigma.GraphicsMill.WinControls.ThumbnailListItem( _
          Aurigma.GraphicsMill.WinControls.StandardFolder.Desktop))
    End If

End Sub
C#
// Parent PIDL (necessary for the Up button)
private Aurigma.GraphicsMill.WinControls.Pidl _parentPidl;

private void JumpToPidl(Aurigma.GraphicsMill.WinControls.Pidl pidl)
{
    // Clear all previously displayed items.
    thumbnailListView1.Items.Clear();

    // If pidl is null, it means that we intend to display the root item.
    // Otherwise we extract all children and display them.
    if (pidl != null)
    {
        // We need to keep the parent PIDL to be able to implement ability
        // to navigate one level up.
        _parentPidl = pidl.Parent;

        // Add all children to the control.
        foreach (Aurigma.GraphicsMill.WinControls.Pidl subPidl in pidl.Items)
        {
            thumbnailListView1.Items.Add(
                new Aurigma.GraphicsMill.WinControls.ThumbnailListItem(subPidl));
        }
    }
    else
    {
        // Root item has no parent.
        _parentPidl = null;

        // Add the root item.
        thumbnailListView1.Items.Add(
            new Aurigma.GraphicsMill.WinControls.ThumbnailListItem(
                Aurigma.GraphicsMill.WinControls.StandardFolder.Desktop));
    }
}

During initialization (for example, in the Form_Load event handler) call this method and pass the PIDL of the start folder, for example:

Visual Basic
JumpToPidl(Aurigma.GraphicsMill.WinControls.Pidl.Create("C:\Temp"))
C#
JumpToPidl(Aurigma.GraphicsMill.WinControls.Pidl.Create(@"C:\Temp"));

Also, you can navigate to standard folders like My Computer:

Visual Basic
JumpToPidl(Aurigma.GraphicsMill.WinControls.Pidl.Create( _
 Aurigma.GraphicsMill.WinControls.StandardFolder.MyComputer))
C#
JumpToPidl(Aurigma.GraphicsMill.WinControls.Pidl.Create(
    Aurigma.GraphicsMill.WinControls.StandardFolder.MyComputer));

If you pass null to this method, the Desktop item (root) will be displayed.

Processing Item Activation

In terms of the ThumbnailListView control, item is activated when it is clicked (either single or double click—depends on control and system settings), or when the user selects it and hits the Enter key. It can be interpreted as an attempt to "open" an item. When it happens, the control raises the ItemActivate event.

When working with PIDL-based items, two kinds of items can be distinguished—folders and files. Folders are containers of other PIDLs (and can be empty though). Files never have children, but they have binary content. To determine what the current PIDL is, the Pidl.Type property can be used.

You need to provide two kinds of behavior when items are activated:

  • When the folder is clicked, the user should navigate to this folder. That is, the PIDL of this folder should be passed to the JumpToPidl method described above.
  • When the file is clicked, and this file is an image supported by the Graphics Mill, it should be opened in BitmapViewer.

To achieve this, add the following ItemActivate event handler:

Visual Basic
Private Sub thumbnailListView1_ItemActivate(ByVal sender As Object, ByVal e As System.EventArgs) _
 Handles thumbnailListView1.ItemActivate

    ' Get the PIDL of the item which is in focus.
    Dim currentPidl As Aurigma.GraphicsMill.WinControls.Pidl = _
     CType(thumbnailListView1.FocusedItem, _
     Aurigma.GraphicsMill.WinControls.ThumbnailListItem).Pidl

    If currentPidl.Type = Aurigma.GraphicsMill.WinControls.PidlType.Folder Then
        ' If this PIDL is a folder, jump to the PIDL of this folder...

        JumpToPidl(currentPidl)
    Else
        '...but if it is a file, attempt to load it into the BitmapViewer

        Try
            bitmapViewer1.Bitmap.Load(currentPidl.Stream)
        Catch ex As Aurigma.GraphicsMill.Codecs.MediaUnsupportedException
            MessageBox.Show("This file format is not supported!")
        End Try
    End If

End Sub
C#
private void thumbnailListView1_ItemActivate(object sender, System.EventArgs e)
{
    // Get the PIDL of the item which is in focus.
    Aurigma.GraphicsMill.WinControls.Pidl currentPidl = 
        ((Aurigma.GraphicsMill.WinControls.ThumbnailListItem)
            (thumbnailListView1.FocusedItem)).Pidl;

    // If this PIDL is a folder, jump to the PIDL of this folder...
    if (currentPidl.Type == Aurigma.GraphicsMill.WinControls.PidlType.Folder)
    {
        JumpToPidl(currentPidl);
    }
    //...but if it is a file, attempt to load it into the BitmapViewer
    else
    {
        try
        {
            bitmapViewer1.Bitmap.Load(currentPidl.Stream);
        }
        catch(Aurigma.GraphicsMill.Codecs.MediaUnsupportedException )
        {
            MessageBox.Show("This file format is not supported!");
        }
    }
}

Implementing Top and Up Buttons

Getting Top and Up buttons working is extremely easy. Each of these buttons should make a single call of the JumpToPidl method.

The Top button should pass null:

Visual Basic
Private Sub buttonTop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 Handles buttonTop.Click
    JumpToPidl(Nothing)
End Sub
C#
private void buttonTop_Click(object sender, System.EventArgs e)
{
    JumpToPidl(null);
}

The Up button should pass the stored parent PIDL:

Visual Basic
Private Sub buttonUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 Handles buttonUp.Click
    JumpToPidl(_parentPidl)
End Sub
C#
private void buttonUp_Click(object sender, System.EventArgs e)
{
    JumpToPidl(_parentPidl);
}

Switching Between Views

The last thing to implement is choice of a view mode. It is also simple. Just change the View property of the control when the user changes the view. In this example, a combo box will be used.

Add four items to the combo box:

  • Thumbnails
  • Icons
  • List
  • Details

Then add the following SelectedIndexChanged event handler:

Visual Basic
Private Sub comboBoxViewMode_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 Handles comboBoxViewMode.SelectedIndexChanged

    Select Case comboBoxViewMode.SelectedIndex
        Case 0
            thumbnailListView1.View = Aurigma.GraphicsMill.WinControls.View.Thumbnails
        Case 1
            thumbnailListView1.View = Aurigma.GraphicsMill.WinControls.View.Icons
        Case 2
            thumbnailListView1.View = Aurigma.GraphicsMill.WinControls.View.List
        Case 3
            thumbnailListView1.View = Aurigma.GraphicsMill.WinControls.View.Details
    End Select
End Sub
C#
private void comboBoxViewMode_SelectedIndexChanged(object sender, System.EventArgs e)
{
    switch(comboBoxViewMode.SelectedIndex)
    {
        case 0:
            thumbnailListView1.View = 
                Aurigma.GraphicsMill.WinControls.View.Thumbnails;
            break;
        case 1:
            thumbnailListView1.View = 
                Aurigma.GraphicsMill.WinControls.View.Icons;
            break;
        case 2:
            thumbnailListView1.View = 
                Aurigma.GraphicsMill.WinControls.View.List;
            break;
        case 3:
            thumbnailListView1.View = 
                Aurigma.GraphicsMill.WinControls.View.Details;
            break;
    }
}

If you allow changing the view mode in some other place (for example, if you add a pop-up menu), it makes sense to track view mode change to be able to update the combo box properly. To do that, handle the ViewChanged event:

Visual Basic
Private Sub thumbnailListView1_ViewChanged(ByVal sender As System.Object, _
 ByVal e As Aurigma.GraphicsMill.WinControls.ViewChangedEventArgs) _
 Handles thumbnailListView1.ViewChanged

    Select Case e.NewView
        Case Aurigma.GraphicsMill.WinControls.View.Thumbnails
            comboBoxViewMode.SelectedIndex = 0
        Case Aurigma.GraphicsMill.WinControls.View.Icons
            comboBoxViewMode.SelectedIndex = 1
        Case Aurigma.GraphicsMill.WinControls.View.List
            comboBoxViewMode.SelectedIndex = 2
        Case Aurigma.GraphicsMill.WinControls.View.Details
            comboBoxViewMode.SelectedIndex = 3
    End Select
End Sub
C#
private void thumbnailListView1_ViewChanged(object sender, 
    Aurigma.GraphicsMill.WinControls.ViewChangedEventArgs e)
{
    switch (e.NewView)
    {
        case Aurigma.GraphicsMill.WinControls.View.Thumbnails:
            comboBoxViewMode.SelectedIndex = 0;
            break;
        case Aurigma.GraphicsMill.WinControls.View.Icons:
            comboBoxViewMode.SelectedIndex = 1;
            break;
        case Aurigma.GraphicsMill.WinControls.View.List:
            comboBoxViewMode.SelectedIndex = 2;
            break;
        case Aurigma.GraphicsMill.WinControls.View.Details:
            comboBoxViewMode.SelectedIndex = 3;
            break;
    }
}

See Also

Reference

Manual