Introduction
I want simulate explorer’s list view with WPF’s ListView. It’s not difficult to retrieve a folder or a file’s icon and its infomations, DirectoryInfo and FileInfo class provide such information I need, to accomplish this task I design below classes.
FileSystemBase
: An abstract class provide the basic information for folder and file, all the information retrieve from a FileSystemInfo instance.
Folder
: Represent a local folder.
File
: Represent a local file.
FileSystemCollection
: the collection of FileSystemBase
, inherit from ObservableCollection
.
When use Binding to show these items in a ListView with GridView style I meet a problem: When load a directory, there are sub folders and files in it, so the Collection contains folders and files, I want to show the Length info of a file, so I bind a GridViewColumn to Length property, the file item can show it correctly, but the folder item doesn’t has a Length property, when load a folder item an exception will be throwed, more folder loaded more exception throwed.
The exception will cause the application become slow, and the most important reason is I don’t like unhandled exception in my application, so I must solve it.
(Exceptions in output window)
To solve this big problem (at least to me it is big) I use CellTemplate
first, in the template I judge whether the given ojbect's type is a File item, if true binding the TextBlock
’s text property to File’s Length property, else set the TextBlock’s text to null. The CellTemplate looks below.
<DataTemplate x:Key="SizeTemplate" >
<TextBlock Name="size" Text="{x:Null}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Type}" Value="{x:Type local:File}">
<Setter TargetName="size" Property="Text" Value="{Binding Length}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
This way work correctly, but it has a observious shortcomming, it is difficult to extend, if there is another object that also have Length property, but isn't a File item, the CellTemplate
can’t show it correctly.
Second I solve this problem with a converter, I tell the converter to retrieve which property’s value, if doesn’t find the property the converter will return null. The converter method.
public object Convert ( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
if ( !string.IsNullOrEmpty ( mPropertyName ) )
{
PropertyDescriptor prop = TypeDescriptor.GetProperties ( value ) [ mPropertyName ];
if ( prop != null )
return prop.GetValue ( value );
else
return null;
}
return null;
}
Definition of PropertyConverter
in XAML and usage.
<local:PropertyConverter x:Key="lengthConverter" PropertyName="Length" />
<GridViewColumn Header="Size" DisplayMemberBinding="{Binding Converter={StaticResource lengthConverter}}" Width="120" />
With this solution there are no exception throwed and the converter is reusable. I am not sure this a good and correct solution for the problem, but it works. If you have much better approach for it, please let me know.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.