WPF学习TreeView和ValueConverter

WPF学习TreeView和ValueConverter

界面代码如下:

<Window x:Class="WPF_TreeView.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:WPF_TreeView"
        mc:Ignorable="d"
        Loaded="Window_Loaded"
        Title="MainWindow" Height="600" Width="400">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="225*"/>
            <ColumnDefinition Width="169*"/>
        </Grid.ColumnDefinitions>

        <TreeView x:Name="FolderView" Grid.ColumnSpan="2" Margin="0,0,-0.4,0.4">
            <TreeView.Resources>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="HeaderTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <!-- Standard data template-->
                                <StackPanel Orientation="Horizontal"  >
                                    <!--Image Width="20" Source="Images/folder_closed.png"/-->
                                    <Image Width="20" Source="{Binding 
                                        RelativeSource={RelativeSource 
                                        Mode=FindAncestor
                                        ,AncestorType={x:Type TreeViewItem}},Path=Tag
                                          ,Converter={x:Static local:HeaderToImageConverter.Instance}}"/>
                                    <TextBlock x:Name="FolderName" VerticalAlignment="Center" Text="{Binding}"/>
                                </StackPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</Window>

后台代码:

using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;

namespace WPF_TreeView
{
	/// <summary>
	/// MainWindow.xaml 的交互逻辑
	/// </summary>
	public partial class MainWindow : Window
	{
		#region Default Constructor
		/// <summary>
		/// Default Constructor
		/// </summary>
		public MainWindow()
		{
			InitializeComponent();
		}
		#endregion
		
		#region  loaded
		/// <summary>
		/// when the application first loaded
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			// Get every logical drive on the machine
			var dirs = Directory.GetLogicalDrives();
			foreach(var drive in dirs)
			{
				// create a new item fot it
				var item = new TreeViewItem();
				// set the header
				item.Header = drive;
				// Add the full path
				item.Tag = drive;

				// add a dummy item
				item.Items.Add(null);

				// Listen out item being expanded
				item.Expanded += FolderExpanded;

				// Add it to the main tree-view	
				FolderView.Items.Add(item);
			}
			
		}
		#endregion

		#region Folder Expanded
		/// <summary>
		/// while the folder expanded find sub folders/fieles
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void FolderExpanded(object sender, RoutedEventArgs e)
		{
			var item = (TreeViewItem)sender;
			if (item.Items.Count != 1 || item.Items[0] != null) return;
			item.Items.Clear();

			#region Get folders
			// Get the full path
			var fullpath = (string)item.Tag;
			// Ceate a blank list for directories
			var directories = new List<string>();
			// try and get directories from the folder
			// ignoring any issues doing so
			try
			{
				var dirs = Directory.GetDirectories(fullpath);
				if (dirs.Length > 0)
					directories.AddRange(dirs);

			}
			catch { }

			// For each directory
			directories.ForEach(directorypath =>
			{
				// Create direcory item
				var subItem = new TreeViewItem()
				{
					// set header as folder name
					Header = GetFileFolderName(directorypath),
					// And tag as fullpath
					Tag = directorypath
				};
				// Add a dummy item so we can expand folder
				subItem.Items.Add(null);

				// Handle expanding
				subItem.Expanded += FolderExpanded;

				// Add subitem to parent item
				item.Items.Add(subItem);

			});
			#endregion

			#region Get files


			// Ceate a blank list for directories
			var files = new List<string>();
			// try and get directories from the folder
			// ignoring any issues doing so
			try
			{
				var fs = Directory.GetFiles(fullpath);
				if (fs.Length > 0)
					files.AddRange(fs);

			}
			catch { }

			// For each file
			files.ForEach(filepath =>
			{
				// Create file item
				var subItem = new TreeViewItem()
				{
					// set header as file name
					Header = GetFileFolderName(filepath),
					
					// And tag as fullpath
					Tag = filepath
					
				};

				// Add subitem to parent item
				item.Items.Add(subItem);

			});
			#endregion


		}

		#endregion

		#region Helpers
		/// <summary>
		/// Get file and folder name from a path
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>
		public static  string GetFileFolderName(string path)
		{
			// If we have no path,retun empty string
			if (string.IsNullOrEmpty(path))
				return string.Empty;
			
			// Make all slashes back slash
			var normalize = path.Replace('/', '\\');
			var lastIndex = normalize.LastIndexOf('\\');

			// If we don't find a backslash,the return the path itself
			if (lastIndex <= 0)
				return path;

			//Return after the name after backslash
			return normalize.Substring(lastIndex + 1);

		}
		#endregion
	}
}

ValueConverter的实现类:

using System;
using System.Globalization;
using System.IO;
using System.Windows.Data;
using System.Windows.Media.Imaging;

namespace WPF_TreeView
{
	/// <summary>
	/// Convert fullpath to a specific image type of a drive,foldeer or file
	/// </summary>
	[ValueConversion(typeof(string),typeof(BitmapImage))]
	public class HeaderToImageConverter : IValueConverter
	{
		public static HeaderToImageConverter Instance = new HeaderToImageConverter();
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			// Get the full path
			var path = (string)value;

			// If the path is null,ignore
			if (path == null)
				return null;

			// Define a image to store the image path
			string image = "Images/file.png";

			// Get the name of file/folder
			var name = MainWindow.GetFileFolderName(path);

			//if the name is blank,we assume it as a drive,as we cannot have a blank file or folder name
			if (string.IsNullOrEmpty(name))
				image = "Images/drive.png";
			else if (new FileInfo(path).Attributes.HasFlag(FileAttributes.Directory))
				image = "Images/folder_closed.png";
			//else if(new FileInfo(path).Attributes.HasFlag(FileAttributes))
			//
			return new BitmapImage(new Uri($"pack://application:,,,/{image}"));
		

		}

		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
	}
}


在这里插入图片描述
参考视频
效果如下:
整个项目的Github地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF(Windows Presentation Foundation)是微软的一种用户界面技术,可用于创建各种Windows应用程序。TreeViewWPF中的一种控件,用于显示层次结构的数据。 当我们需要自定义TreeView时,可以使用WPF提供的各种功能和特性来实现。下面是一些实现自定义TreeView的方法: 1. 自定义树节点的外观:可以使用WPF的样式和模板来修改树节点的外观,例如更改节点的背景颜色、字体样式等。可以使用TreeView控件的ItemTemplate属性来为每个节点定义一个数据模板。 2. 添加功能按钮:可以为TreeView控件添加自己需要的功能按钮,比如展开/折叠按钮、添加/删除节点按钮等。可以使用WPF中的Button控件实现这些按钮,并与TreeView的事件关联。 3. 添加交互行为:可以通过使用WPF提供的命令功能,为TreeView控件添加交互行为。例如,可以为每个节点添加一个命令,当用户双击节点时执行该命令。 4. 实现节点的拖拽和放置:可以通过使用WPF的拖放功能,实现节点的拖拽和放置。可以为每个节点添加一个DragStarted事件,当用户拖动节点时触发该事件,并将节点的数据作为数据对象传递给拖动操作。同时,可以使用TreeViewDropTarget控件作为拖放目标,通过处理Drop事件实现节点的放置。 总的来说,WPF提供了丰富的功能和特性,使我们能够很容易地自定义TreeView控件。通过使用WPF的样式、模板、命令和拖放功能,我们可以实现一个完全符合我们需求的TreeView控件,并为用户提供更好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值