Designing a WPF TreeView File Explorer
I am writing this story to those people who are asking me about the techniques on how to implement a customized TreeView File Explorer control in WPF using Shells.
The output of this tutorial is below.
Please follow the implementation below to achieve the results above.
Implement the PropertyNotifier Class
In WPF, in order for the changes in the class property to reflect in the user interface, the interface INotifyPropertyChanged must be implemented in the class level. In every change in the property, a method OnPropertyChanged must be invoked manually to bubble up the events.
This class will be the base class to be used to trigger the property notifier event as we change the value in each property.
Implement the BaseObject Class
This class will be the base class for all class objects that we will be going to use in this tutorial. This will use the class PropertyNotifier so it will inherit all the behavior of the property change events.
We need to interact directly with the windows kernel, and the calls to this is only valid by importing the shell32.dll and user32.dll and calling the desired methods.
Within the said dlls, the given “shell” methods are requiring some specific variables to retrieve the values. I call the variables “SHGFI”, stands for ShellGetFileInfo, a leverage technique since my early days programming at Visual basic 6.0.
We need to implement the following classes, structs and enums below.
This is the class that will hold the extracted information of the shells.
An enum for the file attribute when calling the shell.
An enum for the shells attribute.
An enum that defines the size of the icon.
An enum used to define the state of the icon (usable in the folder level).
An enum that is used to define the extraction type.
FileSystemObjectInfo.cs and DummyFileSystemObjectInfo.cs
This class is the most important class on this tutorial. It will holds all the drives, folders and files information from the system. It will also handle all the interaction between the user and the UI.
First, we create the constructors.
Notice that we inherited the BaseObject class mentioned earlier on this tutorial.
On the other hand, we need to create a dummy equivalent class of this class. This will be useful on the way on how are we going to manipulate the tree. This is just a simple trick that we can play around.
In the FileSystemObjectInfo.cs, add the following events:
Then add the following properties below.
Add the following methods to trick the TreeView control to allow the trigger in the Expanded event.
This method is used to explore the system directories. It uses the System.IO namespace classes.
Notice how e used the event BeforeExplore and AfterExplore.
This method is used to explore the system files of a directory.
We are almost done, the only left is the actual classes that returns the actual icons of the system using the kernel DLLs.
With this, we need to implement some manager classes.
This class is used to get the actual icons of the system based on the path provided. It uses all the interop variables and methods we have defined in earlier section of this tutorial.
A class that is used to retrieve the icons of the folder from the system.
A class that is used to retrieve the icons of the files from the system.
Putting Everything In Place
By this point in time, we have already declared and implemented all the needed classes of this tutorial. All we gonna have to do is to implement in the User Interface.
But before doing that, we need to place the following codes inside the FileSystemObjectInfo class.
In the constructor:
Add this method as well:
Notice how we use the event PropertyChange, as discussed above in the IPropertyNotifier class, the WPF needs get notified as we interact with the controls via INotifyProperyChanged interface.
In your MainWindow.xaml file, place the code below.
Note: You have to change the namespace TreeViewFileExplorer based on your desired namespace.
And below is the code behind of MainWindow.xaml class.
Voila~~! By running the program, it will give you the desired outcome of this tutorial.
This is the end of this tutorial.
Everything is in place and can be found on my Github account.