WPF中的目录选择器控件

WPF应用程序中,经常需要让用户选择文件或目录。本文将介绍如何创建一个简单的目录选择器控件,它可以被嵌入到对话框窗口中。为了理解本教程,需要具备基本的WPF知识(例如,了解UserControl是什么,DialogWindow是什么等),C#知识(例如,集合、IO和事件),以及WPF中的数据绑定技术。

使用代码

该控件设计了一个位于中间的列表框,一个位于控件上部的文本框,以及一个按钮用于向上导航目录树。以下是页面的代码:

<UserControl x:Class="DirectoryPicker.DPick" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Loaded="UserControl_Loaded"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="30"/> <RowDefinition Height="1*"/> </Grid.RowDefinitions> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="25"/> </Grid.ColumnDefinitions> <TextBox x:Name="txtPath" Grid.Row="0" Margin="5,2" KeyUp="txtPath_KeyUp"/> <Button Content="Up" Grid.Column="1" Margin="2" Click="Button_Click"/> </Grid> <ListBox x:Name="lstDirs" Margin="5" Grid.Row="1" MouseDoubleClick="lstDirs_MouseDoubleClick"/> </Grid> </UserControl>

以下是后台代码:

public partial class DPick : UserControl { ObservableCollection<string> Dirs = new ObservableCollection<string>(); public string CPath { get { return (string)GetValue(CPathProperty); } set { SetValue(CPathProperty, value); } } public static readonly DependencyProperty CPathProperty = DependencyProperty.Register("CPath", typeof(string), typeof(DPick), new PropertyMetadata("")); public DPick() { InitializeComponent(); } private void UserControl_Loaded(object sender, EventArgs e) { this.lstDirs.ItemsSource = Dirs; if (CPath == String.Empty || Directory.Exists(CPath) == false) { CPath = ""; foreach (string s in Directory.GetLogicalDrives()) { Dirs.Add(s); } this.txtPath.Text = CPath; } else { PopulateList(); } } private void lstDirs_MouseDoubleClick(object sender, MouseButtonEventArgs e) { int SelIndex = this.lstDirs.SelectedIndex; CPath = System.IO.Path.Combine(CPath, Dirs[SelIndex]); PopulateList(); } private void PopulateList() { try { Dirs.Clear(); foreach (var dir in Directory.GetDirectories(CPath)) { Dirs.Add(GetDirName(dir)); } this.txtPath.Text = CPath; } catch (Exception) { Dirs.Clear(); Dirs.Add("Access Denied"); } } private string GetDirName(string Path) { return Path.Substring(Path.LastIndexOf('\\') + 1); } private void Button_Click(object sender, RoutedEventArgs e) { CPath = System.IO.Path.GetDirectoryName(CPath); PopulateList(); } private void txtPath_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { string old = CPath; try { CPath = this.txtPath.Text; PopulateList(); } catch (Exception) { CPath = old; } } } private void btnOK_Click(object sender, RoutedEventArgs e) { } }

在代码中,首先定义了一个ObservableCollection<string>,它定义了当前目录的内容。然后定义了一个名为CPath的依赖属性,它代表控件当前的路径。可以将CPath设置为一个初始目录,但它也是控件当前所在的目录(即用户到目前为止已选择的目录)。

接下来,UserControl_Loaded方法被调用。如果CPath属性已被设置并且目录存在,则将其用作控件的初始目录,否则列表将被填充为LogicalDrives的列表。

然后,调用PopulateList方法。这个方法清除ObservableCollection(以及ListBox),然后开始将当前目录的内容(仅目录名)作为字符串添加到其中。如果发生错误,或者目录不再存在(用户可能在控件已经更新后删除了它),或者没有访问该目录的权限,那么将字符串"Access Denied"添加到列表中。

ListBox_MouseDoubleClick事件在代码中定义。当用户双击列表框或其子项时,将触发此事件。这是因为事件冒泡。事件冒泡表示事件可以沿着控件树向上传播并到达主容器。例如,如果双击列表框中的一个项,列表框和UserControl都会被双击。在这种情况下,获取选定的索引,并使用静态类Path.Combine的帮助将其添加到CPath字符串中。

为了"向上导航",可以使用静态类Path,该类有一个方法GetDirectoryName,它返回另一个元素所在的目录的路径。在这种情况下,这个元素是一个目录,所以可以使用这段代码来向上导航。例如,从C:\Dir1\Dir2\Dir3,Path.GetDirectoryName(string)将返回C:\Dir1\Dir2。

最后一点:如果在文本框中输入一个路径,并且用户按下Enter键,控件将自动导航到指定的目录(如果它存在)。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485