[更新至V2]WPF:MVVM簡單檔案瀏覽器

來源:互聯網
上載者:User

 

 

原始碼下載 
2.0 下載頁面

1.0 下載頁面

注意:連結是微軟SkyDrive頁面,下載時請用瀏覽器直接下載,用某些下載工具可能無法下載

原始碼環境:Microsoft Visual C# 2008 Express

 

程式ViewModel名稱是FileSystemObjectViewModel,它把檔案和檔案夾統一視為一類,並用FileSystemObjectType枚舉來區分類型。ViewModel的邏輯很簡單,這裡就不再多說了,下面主要介紹一些其他需要注意的地方。

建議下載原始碼作參考。

 

在2.0後:

程式使用.NET 4.0中Directory類型所支援的EnumerateDirectories和EnumerateFiles方法。

 

即時資料載入

檔案瀏覽器最基本的效能考慮就應該是資料的即時載入,也就是說展開的資料夾檢視都是在使用者進行TreeViewItem的展開操作之後才被載入的,當然資料夾檢視收縮後已經載入的資料是不會被扔掉的,下次展開會直接開啟已經載入的資料。

那麼每當一個ViewModel被建立後,初始化函數會進行這樣一種操作,如果它是檔案夾的話,快速檢查當前檔案夾是否有子成員(子檔案夾或子檔案),如果有的話,把一個特殊的沒有任何值的特殊ViewModel加在當前ViewModel的Children屬性中。這樣WPF資料繫結會在當前產生的TreeViewItem的Items加入這個由特殊ViewModel所產生的另一個TreeViewItem,當前TreeViewItem左側會顯示“加號”,代表著當前檔案夾有子成員,而事實上,子成員的具體內容只有當該檔案夾被使用者展開後才會被載入。

MVVM中View中是沒有事件代碼的,只有XAML,因此我們首先要利用TreeViewItem的IsExpanded相依性屬性,同時ViewModel中也有IsExpanded屬性,用雙向的資料繫結使這兩個屬性可以互相設定(在本例中其實只存在View設定ViewModel的情況)。

 

 

參考FileSystemObjectViewModel中的OnExpanded方法:  

/// <summary>

/// 節點被展開後的操作

/// </summary>

protected virtual void OnExpanded()

{

    //是否有特殊節點

    if (HasSpecialChild)

    {

        //將要展開的節點擁有沒有列舉的子成員(第一次開啟)

 

        //我們需要移除特殊節點,並將子檔案夾加入到Children中

        RemoveSpecialChild();

 

        foreach (var dir in GetSubDirs())

            _Children.Add(new FileSystemObjectViewModel(dir, FileSystemObjectType.Folder));

        foreach (var file in GetSubFiles())

            _Children.Add(new FileSystemObjectViewModel(file, FileSystemObjectType.File));

    }

}

 

開啟TreeView的虛擬化

  在.NET 3.5後,微軟增加了VirtualizingStackPanel對TreeView的支援,虛擬化可以使TreeView得到更客觀的效能,但是需要手動聲明VirtualizingStackPanel的附加屬性來使虛擬化起作用。

<TreeView VirtualizingStackPanel.IsVirtualizing="True"

          VirtualizingStackPanel.VirtualizationMode="Recycling"></TreeView>

VirtualizingStackPanel.VirtualizationMode預設是Standard:建立並丟棄項容器,應該儘可能的使用Recycling:重用項容器。

 

 

從檔案或檔案夾中提取表徵圖

Windows Forms中有Icon.ExtractAssociatedIcon(MSDN:http://msdn.microsoft.com/en-us/library/system.drawing.icon.extractassociatedicon.aspx),但其缺點是無法從提取檔案夾(包括磁碟根目錄)的表徵圖,並且在WPF程式中使用需要額外引用System.Drawing命名空間DLL。

因此使用SHGetFileInfo本地Windows API(MSDN:http://msdn.microsoft.com/en-us/library/bb762179.aspx),並將非託管表徵圖資源轉換成WPF的BitmapSource。

感謝互連網,就直接用這個連結所提供的代碼來做SHGetFileInfo的執行:(http://stackoverflow.com/questions/6008600/get-program-icons),我把它包在一個叫IconExtractor的類中。

 

 

View

      主View:FileSystemView使用ObjectDataProvider來調用ViewModel(FileSystemObjectViewModel)的靜態方法來索取當前系統的所有磁碟根目錄並將結果綁定在TreeView的DataContext上。

  資源中還包括一個自訂的資料轉換器(IconConverter)用來將FileSystemObjectViewModel轉換成相應的檔案或檔案夾表徵圖,並通過Image顯示在TreeView的HierarchicalDataTemplate中。

 

FileSystemView:

<UserControl.Resources>

    <ObjectDataProvider x:Key="dataProvider"

                       ObjectType="loc:FileSystemObjectViewModel"

                       MethodName="GetSystemDrives"/>

 

    <loc:IconConverter x:Key="iconConverter" />

 

</UserControl.Resources>

<TreeView VirtualizingStackPanel.IsVirtualizing="True"

         VirtualizingStackPanel.VirtualizationMode="Recycling"

         DataContext="{Binding Source={StaticResource dataProvider}}"

         ItemsSource="{Binding Children}">

 

    <TreeView.ItemTemplate>

        <HierarchicalDataTemplate DataType="loc:FileSystemObjectViewModel"

                                 ItemsSource="{Binding Children}">

 

            <StackPanel Orientation="Horizontal">

                <Image Source="{Binding Converter={StaticResource iconConverter}}" />

                <TextBlock Text="{Binding DisplayName}" />

            </StackPanel>

 

        </HierarchicalDataTemplate>

    </TreeView.ItemTemplate>

 

    <TreeView.ItemContainerStyle>

        <Style TargetType="TreeViewItem">

            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />

        </Style>

    </TreeView.ItemContainerStyle>

 

</TreeView>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.