Click here to Skip to main content
15,885,141 members
Articles / Desktop Programming / WPF
Alternative
Article

A WPF File ListView and ComboBox (Version II)

Rate me:
Please Sign up or sign in to vote.
4.97/5 (16 votes)
30 Jul 2014CPOL7 min read 60.7K   2.6K   46   21
This is an alternative for "A WPF File ListView and ComboBox"

The project is now maintained here: https://github.com/Dirkster99/fsc (Version III) and the current article is here.

Introduction  

I was recently asked to add a 'File Tree Pane' into my editor (https://edi.codeplex.com/discussions/541888) and went looking for a good solution, because the component is really missing and it really bothers me too. The best solution I found, was written by Thomas Willwacher, as usual, here at CodeProject. I really like the concept that Thomas is using and reviewed the project in terms of integrating it in my editor, and while that is still too come, I found already some issues that would probably be difficult to fix in a project that is driven by an IoC (which I'd like to do next).

Image 1 Image 2

It is difficult to write this down correctly, so do not get me wrong here, I am really grateful that Thomas has posted his solution. Because I am not even sure whether I could have developed such a nice File Explorer concept to start with. But I saw architectural issues and I decided to get this done instead of putting it off. So, here is my take on this solution. I am posting it here in the hope that it is useful to others and that we might be able to develop this even further.

Background

The solution presented here is about a File Explorer control that can be used in a Tool Window. The user should be able to browse directories, list their files, filter on the listed files, and open files via double click, drag & drop and context menu. The Drag & Drop and Context menu part is not presented here since I do not think this would be hard to add. The solution presented here is just about the same test application that Thomas had posted in his article. I only added a directory browser control and developed the architecture from scratch with MVVM in mind.

Using the code

The current articles discusses the code in FileListView_Version2.zip in the download section. The FileListView_Version2.1.zip in the download section is a refactored version that is currently under development based on my observations and Leung Yat Chun's suggestions in the forum's section. 

Re-using the code of the provided solution requires that you reference the Dll assemblies (FileListView and FolderBrowser), and copy & parts of the MainWindow.xaml code into your own view implementation. You will also need the code MainWindow.xaml.cs to create the necessary viewmodels. This is about all you need to re-use this solution in your own projects.

Points of Interest

The solution presented here contains 4 projects:

  • FileListView, FileListViewTest and
  • FolderBrowser, TestFolderBrowser.

The FileListView project is the assembly that contains the meat of the File Explorer controls that this article is focusing on. The FolderBrowser project originates from a different CodeProject article [2] and was included here since I felt that I did not need a Recent Files selection but a Recent Locations selection. So, re-factored this solution, as well, and included the result here.

The 'Test' projects in this solution contain a demo application that can be executed to check out how things work. The remainder of this article will focus on the FileListView project but feel free to ask questions/demand more information if you feel that I should document the FolderBrowser part in more detail.

The Views in the FileListView Project

The FileListView project is mainly partitioned in 3 views that are completely separated from each other.

Image 3

FilterComboBox

The FilterComboBox inherits from the ComboBox control [3] and should be fully theme-able since I'd like to support bright and dark skins. This is basically the control where you enter such filter as: '*.png', '*.*', or (I extended this) '*.png|*.jpg|*.jpeg'. This filter is then applied to the list of files when the user selects the filter or presses the enter key in the text portion of the combobox.

XML
<fview:FilterComboBox DataContext="{Binding FolderView.Filters}"
                      ItemsSource="{Binding CurrentItems}"
                      SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}"
                      Text="{Binding CurrentFilter, UpdateSourceTrigger=PropertyChanged}"

                      fvbehav:SelectionChangedCommand.ChangedCommand="{Binding SelectionChanged}"
                      VerticalAlignment="Top"
                      HorizontalAlignment="Stretch"
                      Grid.Column="3"
                      Margin="3"
                    /> 

The above code shows how the FilterComboBox control is implemented in the MainWindow's Xaml. A noteworthy item is the SelectionChangedCommand behavior [4] which is basically a custom ComboBox behavior that binds itself to to the KeyUp and SelectionChanged event of the combobox. The behavior executes the bound SelectionChanged command in the FolderComboBoxViewModel when either event occurs. This in turn executes the SelectionChanged_Executed method which evaluates whether the currently entered path refers to a valid directory or not. The method raises the OnCurrentPathChanged event of the FolderChangedEventArgs type if the entered path was in fact in existence. This event is received by another viewmodel discussed further below.

FolderComboBox

The FolderComboBox control is the combobox that keeps the list of folders that a user can select as the base of his exploration. This includes the usual suspects, such as, Desktop, My Documents, and Drives but also contains a list of Recent Locations:

Image 4

The FolderComboBox makes also use of the SelectionChanged behavior discussed above. It is very similar to the FilterComboBox except for 2 additions:

XML
<Setter Property="ItemTemplate">
  <Setter.Value>
    <DataTemplate DataType="{x:Type vm:FSItemVM}">
      <Grid ToolTip="{Binding FullPath}" ToolTipService.IsEnabled="{Binding ShowToolTip}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="{Binding Indentation}"/>
          <ColumnDefinition Width="20"/>
          <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition />
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Grid.Column="1" Source="{Binding Path=DisplayIcon}" Width="16" Height="16"/>
        <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding DisplayName}" />
      </Grid>
    </DataTemplate>
  </Setter.Value>
</Setter>

This ItemTemplate shows tha items display in the drop-down section of the ComboBox consist of an Image and a TextBlock. The ItemTemplate binds to instances of the ItemVM type which is part of the ObservableCollection<FSItemVM> CurrentItems collection in the FolderComboBoxViewModel.

XML
<Setter Property="ItemContainerStyle">
  <Setter.Value>
    <Style TargetType="{x:Type ComboBoxItem}" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
      <Style.Triggers>
        <DataTrigger Binding="{Binding}" Value="{x:Null}">
          <Setter Property="IsEnabled" Value="False" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                <Separator Width="0" Height="10"/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Setter.Value>
</Setter>

The 2nd interesting thing in the FolderComboBox control is the ItemContainerStyle which includes a DataTrigger that inserts a Seperator when the bound value is null. The above Xaml literally converts a value of null into a seperator entry in the drop down list. This little trick inserts a Seperator in the drop-down list that allows us to group items such that users cannot click into the extra space (since seperators are not hit test visible).

FListView

The FListView is basically an out of the box ListView with an attached behavior addition that converts a double click into a bound DoubleClickCommand in the FileListViewViewModel [5].

The ViewModels in the FileListView Project

This solution includes a few more viewmodels than the original version 1. There is basically 1 viewmodel for each of the three controls documented in the previous section. The FolderComboBoxViewModel and the FileListViewModel make use of the FSItemVM class to manage their file specific collections. The FolderListViewModel is the heart of the solution since it instantiates the other control specific viewmodels and manages their events when they say, hey:

  • ...just selected a new Folder
    (OnCurrentPathChanged in FolderComboBoxViewModel and FileListViewModel)
  • ...just selected a new Filter (OnFilterChanged in FilterComboBoxViewModel)
  • ...just want to open a file (OnFileOpen in FileListViewModel)

Image 5

 

Conclusions

 

Converting this project took me about 3-4 days of work but I think it was worth it since I have a much clearer understanding now and feel motivated to add other toys such as an async query and load of the FileListView. This could include a stop button shown in the Folder or Filter combobox to stop process that may take extra ordinary long when accessing slow devices.

Over all I have learned a few more tricks looking deep into someone else's code, so I am once again grateful for being part of this community. And now I am looking forward to see what the community thinks about this.

Credits

The Class diagrams in this article were drawn with #Develop (http://www.icsharpcode.net/opensource/sd/).  I would like to say thank you for the original article and code version and the tips from Leung Yat Chun here at code project.

References 

  • [1] A WPF File ListView and ComboBox (Version I) by Thomas Willwacher
    http://www.codeproject.com/Articles/167873/A-WPF-File-ListView-and-ComboBox
  • [2] WPF Folder Browser by Erik Rude
    http://www.codeproject.com/Articles/352874/WPF-Folder-Browser
  • [3] Inheriting from a Look Less WPF Control
    http://www.codeproject.com/Articles/575645/Inheriting-from-a-Look-Less-WPF-Control
  • [4] Patterns in Attached Behaviors
    http://www.codeproject.com/Articles/422537/Patterns-in-Attached-Behaviours
  • [5] AttachedCommandBehavior V2 aka ACB
    http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/

History

  • 16.04.2014 Initial creation
  • 02.06.2014 Updated Version 2.1 to include metro design icons, a tree browser in the tool window area and much more (see Readme.txt files in zip archive) - next I'll either update the article or develop this even further :-) if I get the time to do either thing...

License

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


Written By
Germany Germany
The Windows Presentation Foundation (WPF) and C# are among my favorites and so I developed Edi

and a few other projects on GitHub. I am normally an algorithms and structure type but WPF has such interesting UI sides that I cannot help myself but get into it.

https://de.linkedin.com/in/dirkbahle

Comments and Discussions

 
SuggestionAuto Refresh Pin
User 917474117-Nov-16 3:20
professionalUser 917474117-Nov-16 3:20 
GeneralRe: Auto Refresh Pin
Dirk Bahle28-Nov-16 7:01
Dirk Bahle28-Nov-16 7:01 
GeneralRe: Auto Refresh Pin
User 917474128-Nov-16 13:41
professionalUser 917474128-Nov-16 13:41 
QuestionInitial Path Pin
User 917474116-Nov-16 4:08
professionalUser 917474116-Nov-16 4:08 
AnswerRe: Initial Path Pin
Dirk Bahle16-Nov-16 9:57
Dirk Bahle16-Nov-16 9:57 
GeneralRe: Initial Path Pin
User 917474117-Nov-16 3:06
professionalUser 917474117-Nov-16 3:06 
GeneralRe: Initial Path Pin
Dirk Bahle28-Nov-16 6:59
Dirk Bahle28-Nov-16 6:59 
GeneralRe: Initial Path Pin
User 917474128-Nov-16 13:40
professionalUser 917474128-Nov-16 13:40 
QuestionResolved - Using a library so Application.Current was null Pin
phill_mn24-Apr-15 8:16
phill_mn24-Apr-15 8:16 
AnswerRe: Resolved - Using a library so Application.Current was null Pin
Dirk Bahle25-Apr-15 23:49
Dirk Bahle25-Apr-15 23:49 
QuestionApp Crash when loading Windows - related to Behaviors Pin
phill_mn24-Apr-15 4:05
phill_mn24-Apr-15 4:05 
AnswerRe: App Crash when loading Windows - related to Behaviors Pin
phill_mn24-Apr-15 4:58
phill_mn24-Apr-15 4:58 
GeneralRe: App Crash when loading Windows - related to Behaviors Pin
Dirk Bahle25-Apr-15 23:53
Dirk Bahle25-Apr-15 23:53 
GeneralAnother version Pin
Leung Yat Chun8-May-14 7:10
Leung Yat Chun8-May-14 7:10 
GeneralRe: Another version Pin
Dirk Bahle11-May-14 7:03
Dirk Bahle11-May-14 7:03 
GeneralRe: Another version Pin
Leung Yat Chun11-May-14 9:24
Leung Yat Chun11-May-14 9:24 
GeneralRe: Another version Pin
Dirk Bahle12-May-14 11:49
Dirk Bahle12-May-14 11:49 
GeneralRe: Another version Pin
Leung Yat Chun12-May-14 21:56
Leung Yat Chun12-May-14 21:56 
GeneralRe: Another version Pin
Dirk Bahle13-May-14 12:05
Dirk Bahle13-May-14 12:05 
QuestionVery interesting article about one alternative to a WPF File ListView & ComboBox Pin
Volynsky Alex16-Apr-14 23:08
professionalVolynsky Alex16-Apr-14 23:08 
AnswerRe: Very interesting article about one alternative to a WPF File ListView & ComboBox Pin
Dirk Bahle17-Apr-14 0:49
Dirk Bahle17-Apr-14 0:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.