结构
RelayCommand
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WpfApp
{
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged = (sender, e) => { };
private Action action { get; set; }
public bool CanExecute(object parameter)
{
return true;
}
public RelayCommand(Action actions)
{
this.action = actions;
}
public void Execute(object parameter)
{
action();
}
}
}
DirectoryItemType
namespace WpfApp
{
public enum DirectoryItemType
{
Driver,
File,
Folder
}
}
DirectoryItem
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
namespace WpfApp
{
public class DirectoryItem:BaseViewModel
{
public string FullPath { get; set; }
public DirectoryItemType ItemType { get; set; }
public string Name { get { return this.ItemType == DirectoryItemType.Driver ? this.FullPath : DirectoryStruc.GetFileFolerName(this.FullPath); } set { } }
public ObservableCollection<DirectoryItem> Children { get; set; }
public bool CanExpand { get { return this.ItemType != DirectoryItemType.File; } }
public bool IsExpanded
{
get { return this.Children?.Count(f => f != null) > 0; }
set {
if (value == true)
Expand();
else
this.ClearChildren();
}
}
private void ClearChildren()
{
this.Children = new ObservableCollection<DirectoryItem>();
if (this.ItemType != DirectoryItemType.File)
{
this.Children.Add(null);
}
}
public ICommand ExecuteExpandCommand { get; set; }
public DirectoryItem(DirectoryItemType directoryItemType,string fullPath)
{
this.ExecuteExpandCommand = new RelayCommand(Expand);
this.ItemType = directoryItemType;
this.FullPath = fullPath;
}
private void Expand()
{
if (this.ItemType == DirectoryItemType.File)
return;
var child = DirectoryStruc.GetDirectoryContents(this.FullPath);
this.Children = new ObservableCollection<DirectoryItem>(child.Select(a => new DirectoryItem(a.ItemType, a.FullPath)));
}
}
}
DirectoryStruc
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace WpfApp
{
public class DirectoryStruc
{
public static string GetFileFolerName(string fullPath)
{
if (string.IsNullOrEmpty(fullPath))
{
return string.Empty;
}
var path = fullPath.Replace('/', '\\');
var index = path.LastIndexOf('\\');
if (index <= 0)
return fullPath;
return fullPath.Substring(index + 1);
}
public static List<DirectoryItem> GetList()
{
return Directory.GetLogicalDrives().Select(x => new DirectoryItem(DirectoryItemType.Driver,x)).ToList();
}
public static List<DirectoryItem> GetDirectoryContents(string fullPath)
{
var items = new List<DirectoryItem>();
var dirs = Directory.GetDirectories(fullPath);
if (dirs.Length > 0)
items.AddRange(dirs.Select(dir => new DirectoryItem(DirectoryItemType.Folder,dir)));
var fs = Directory.GetFiles(fullPath);
if (fs.Length>0)
{
items.AddRange(fs.Select(dir => new DirectoryItem(DirectoryItemType.File,dir )));
}
return items;
}
}
}
BaseViewModel 添加引用PropertyChanged.Fody 1.52.1版本
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PropertyChanged;
namespace WpfApp
{
[ImplementPropertyChanged]
public class BaseViewModel:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
}
}
MainWindowsViewModel
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp
{
public class MainWindowsViewModel:BaseViewModel
{
public ObservableCollection<DirectoryItem> Items { get; set; }
public MainWindowsViewModel()
{
var child = DirectoryStruc.GetList();
this.Items = new ObservableCollection<DirectoryItem>( child.Select(a => new DirectoryItem(a.ItemType, a.FullPath)).ToList());
}
}
}
xaml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TreeView x:Name="folderView" ItemsSource="{Binding Items}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded,Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ItemType,Converter={x:Static local:ValueConverter.Instance }}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
ValueConverter
在这里插入代码片
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media.Imaging;
namespace WpfApp
{
public class ValueConverter:IValueConverter
{
public static ValueConverter Instance = new ValueConverter();
public object Convert(object value, Type targetType,object parameter,CultureInfo culture )
{
var image = "Image\\driver.png";
switch ((DirectoryItemType)value)
{ case DirectoryItemType.Driver:
image = "Image\\driver.png";
break;
case DirectoryItemType.Folder:
image = "Image\\folder.png";
break;
}
return new BitmapImage(new Uri($"pack://application:,,,/{image}"));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}