c#的winform TreeView控件中,展开不同的节点,右边显示不同的内容,该怎么做啊,请帮帮我吧,谢谢~
一个tabcontrol里有好多tabpag,我可以在每一个tabpage中添加不同的控件和内容。类似地,我是想在不同的子节点里添加控件和容器,该怎么办呢~...
一个tabcontrol里有好多tabpag,我可以在每一个tabpage中添加不同的控件和内容。类似地,我是想在不同的子节点里添加控件和容器,该怎么办呢~
展开
2个回答
展开全部
可参考如下信息:
树形控件是以树形结构表达元素的方式,是比较常用的控件之一,在WPF控件库中,同样提供了树形控件--TreeView。
在WPF中,TreeView控件只是提供显示容器,具体的节点通过TreeViewItem完成,TreeView控件的Items属性表示了它所包含的子节点。TreeViewItem控件是一个可递归的控件,它也用Items属性表示子节点,层层深入,构成一个完整的树形结构。
可以通过TreeView控件的Items属性添加和删除它的子节点,Items属性的每个元素都是object类型,所以可以包含任意类型的元素,TreeView在显示时会自动通过元素的ToString()方法获取要显示的文本。在这一点上TreeViewItem和TreeView是完全一致的。
TreeView控件不包含节点展开和收拢事件(这和Win Form窗体中的Tree控件不同),它包含SelectedItemChanged事件,用来监视树形结构中选中节点的变化。
TreeViewItem控件具有展开(Expanded)事件和收拢(Collapsed)事件,通过这两个事件可以监视节点的展开和收拢,并给出相应的处理。
在TextReader实例中,要显示目录和文件结构,需要用一种典型的树状结构,所以TreeView控件是首选。本例通过以下思路来完成目录的动态加载:
(1)文件系统中的目录和文件都作为TreeView控件中的节点,用TreeViewItem空间表示,而目录和文件的详细路径则保存在TreeViewItem.Tag属性中。
(2)在窗体启动时加载操作系统中所有的逻辑分区(例如,C:\、D:\等),实际上它们都是目录。
(3)监视树中节点的Expanded事件,如果是一个目录第一次展开,则加载该目录下直接的所有子目录和文件,不包括子目录的子目录和文件。
(4)监视TreeView控件的SelectedItemChanged事件,并根据当前选中节点的路径获取目录或文件的详细属性,并显示到界面上。
(5)当双击TreeView控件中的节点时,如果节点是文件,则判断文件类型;如果节点是文本格式文件,则将文本内容加载到界面上。
示例代码9-18是TextReader中与TreeView控件有关的代码,其中LoadLogicDrive()方法将系统中的逻辑分区信息加载到TreeView控件中,LoadDicTree()方法则将选中目录中的子目录和文件加载到该目录节点下。Dic_Expanded()是所有目录节点的Expanded事件处理函数,它首先判断该目录是不是第一次展开,如果是则加载该目录下的信息,否则不加载。
示例代码9-18:
namespace FileViewer{/// <summary>/// Window1.xaml 的交互逻辑/// </summary>public partial class WndMain : Window{public WndMain( ){InitializeComponent( );}
/// <summary>/// 加载指定目录下的文件和目录/// </summary>/// <param name="tv">要展开的目录</param>/// <returns>true则表示加载成功</returns>private bool LoadDicTree(TreeViewItem tvi){tvi.Items.Clear( ); //清除原有的所有节点(第一次展开标记) //获取目录路径string dicStr = ((string) tvi.Tag).Trim( );if (Directory.Exists(dicStr)) //如果目录存在{//获取目录信息DirectoryInfo dicInfo = new DirectoryInfo(dicStr);//遍历目录中所有子目录foreach (DirectoryInfo item in dicInfo.GetDirectories()){//如果为系统目录,则不显示到界面if ((item.Attributes & FileAttributes.System) == FileAttributes.System)continue;//创建TreeViewItem对象TreeViewItem tviDic = new TreeViewItem( );//保存目录路径到Tag属性tviDic.Tag = item.FullName;//设置节点显示文本tviDic.Header = item.Name;//节点添加一个子节点"tmp"作为第一次展开标记tviDic.Items.Add("tmp");//添加节点Expanded事件处理函数tvi.Expanded += new RoutedEventHandler(this.Dic_Expanded);//将节点添加到该父目录下tvi.Items.Add(tviDic);}//遍历目录中所有子文件foreach (FileInfo item in dicInfo.GetFiles()){//创建TreeViewItem对象TreeViewItem tviFile = new TreeViewItem( );//保存文件路径到Tag属性tviFile.Tag = item.FullName;//设置节点显示文本tviFile.Header = item.Name;//将节点添加到父目录下tvi.Items.Add(tviFile);}return true;}else //目录不存在,不处理{return false;}}
//加载系统中逻辑分区信息到目录树private void LoadLogicDrive( ){//遍历所有逻辑分区foreach (string drv in Directory.GetLogicalDrives()){//创建TreeViewItem对象TreeViewItem tvi = new TreeViewItem( );//将分区路径保存到Tag属性 tvi.Tag = drv;//设置节点显示文本tvi.Header = drv;//添加节点Expanded事件处理函数tvi.Expanded += new RoutedEventHandler(this.Dic_Expanded);//是目录,则添加"tmp"字符串子节点,用作第一次展开标记tvi.Items.Add("tmp"); //将节点添加到目录树this.tvDic.Items.Add(tvi); }}
//窗体加载事件处理函数private void Window_Loaded(object sender, RoutedEventArgs e){this.tvDic.Items.Clear( ); //清除目录树中所有节点this.LoadLogicDrive( ); //加载操作系统中所有逻辑分区}
//节点展开事件处理函数void Dic_Expanded(object sender, RoutedEventArgs e){//获取展开的节点TreeViewItem tvi = (TreeViewItem) e.Source;if (tvi.Tag == null) //如果节点不带有Tag数据,则返回{return;}if ((tvi.Items.Count == 1) && //如果节点Tag数据是string类型且为"tmp"(tvi.Items[0] is string) && //则是第一次展开,则加载子目录等信息到树形结构中((string) tvi.Items[0] == "tmp")){this.LoadDicTree(tvi); //加载目录的子目录和文件}}
//选中文件或目录发生变化事件处理函数privatevoidtvDic_SelectedItemChanged(objectsender,RoutedPropertyChangedEventArgs <object> e){//获取该节点的路径string dicStr = (string)((TreeViewItem) this.tvDic.SelectedItem).Tag;if (Directory.Exists(dicStr)) //是一个目录{//显示属性面板this.tabView.Visibility = Visibility.Visible;//获取目录信息DirectoryInfo dicInfo = new DirectoryInfo(dicStr);string hint = ""; //生成目录属性文本hint += string.Format("目 录: {0}\n", dicInfo.Name);hint += string.Format("路 径 {0}\n", dicInfo.FullName);hint += string.Format("根 目 录: {0}\n", dicInfo.Root);hint += string.Format("父 目 录: {0}\n", dicInfo.Parent);hint += string.Format("子 目 录 数: {0}\n", dicInfo.GetDirectories( ).Length);hint += string.Format("文 件 数: {0}\n", dicInfo.GetFiles( ).Length);hint += string.Format("创 建 时 间: {0}\n", dicInfo.CreationTime);hint += string.Format("最近访问时间: {0}\n", dicInfo.LastAccessTime);hint += string.Format("最近修改时间: {0}\n", dicInfo.LastWriteTime);hint += string.Format("目 录 属 性: {0}\n", dicInfo.Attributes);this.tbProp.Text = hint; //显示目录属性到界面}else if (File.Exists(dicStr)) //是一个文件{//显示属性面板this.tabView.Visibility = Visibility.Visible;//获取文件属性FileInfo fileInfo = new FileInfo(dicStr);string hint = ""; //生成文件属性文本hint += string.Format("文 件 名: {0}\n", fileInfo.Name);hint += string.Format("完 整 路 径: {0}\n", fileInfo.FullName);hint += string.Format("扩 展 名: {0}\n", fileInfo.Extension);hint += string.Format("父 目 录: {0}\n", fileInfo.Directory);hint += string.Format("创 建 时 间: {0}\n", fileInfo.CreationTime);hint += string.Format("最近访问时间: {0}\n", fileInfo.LastAccessTime);hint += string.Format("最近修改时间: {0}\n", fileInfo.LastWriteTime);hint += string.Format("文 件 属 性: {0}\n", fileInfo.Attributes);this.tbProp.Text = hint; //显示文件属性到界面}else{ //不是文件也不是目录,隐藏属性面板this.tabView.Visibility = Visibility.Hidden;}}
//目录树双击事件处理函数private void tvDic_MouseDoubleClick(object sender, MouseButtonEventArgs e){//获取双击发生的节点TreeViewItem tvi = (TreeViewItem) this.tvDic.SelectedItem;
if (tvi == null) //如果节点为空,返回{return;}
if (tvi.Items.Count > 0) //是目录,不是文件,返回{return;}
string fileName = (string) tvi.Tag; //获取文件名if (!File.Exists(fileName)) //文件不存在,返回{return;} //获取文件信息FileInfo fInfo = new FileInfo(fileName);//根据后缀名判断是否为文本格式的文件switch (fInfo.Extension.ToUpper( )) {case ".TXT": //文本文件case ".LOG": //日志文件case ".INI": //ini配置信息case ".XML": //xml文件case ".XAML": //xaml代码文件case ".BAT": //批处理文件case ".CPP": //C++代码文件case ".C": //C代码文件case ".H": //C、C++头文件case ".CS": //C#代码文件case ".VB": //VB代码文件case ".HTML": //Html网页代码文件case ".ASPX": //ASP.NET代码文件case ".VBS": //VBScript代码文件case ".JS": //JavaScript代码文件case ".CSS": //CSS格式定义文件case ".SLN": //VS解决方案文件this.ViewTxtFile(fileName); //加载文本文件到界面上break;case ".RTF":this.ViewRtfFile(fileName); //加载rtf文件到界面上break;default://提示不支持的文件格式MessageBox.Show("暂时还不支持该类型文件查看!", "提示",MessageBoxButton.OK, MessageBoxImage.Information);break;}}}}
实例TextReader中目录树的运行效果如图9-13所示,其中,界面左边是目录树,没有展开的目录也没有加载任何信息,只有在第一次展开之后才会加载具体的目录信息。界面右边的属性页面显示了当前选中文件或目录的详细属性,通过代码中的tvDic_SelectedItem Changed()方法实现。
(点击查看大图)图9-13 TextReader目录树运行效果
技巧:在实例TextReader中,目录树加载之所以分目录进行加载,主要是为了提高效率,一次性加载所有目录信息需要等待很长时间,而且并不是所有目录信息都会用到,真正使用的其实是很少的一部分。
树形控件是以树形结构表达元素的方式,是比较常用的控件之一,在WPF控件库中,同样提供了树形控件--TreeView。
在WPF中,TreeView控件只是提供显示容器,具体的节点通过TreeViewItem完成,TreeView控件的Items属性表示了它所包含的子节点。TreeViewItem控件是一个可递归的控件,它也用Items属性表示子节点,层层深入,构成一个完整的树形结构。
可以通过TreeView控件的Items属性添加和删除它的子节点,Items属性的每个元素都是object类型,所以可以包含任意类型的元素,TreeView在显示时会自动通过元素的ToString()方法获取要显示的文本。在这一点上TreeViewItem和TreeView是完全一致的。
TreeView控件不包含节点展开和收拢事件(这和Win Form窗体中的Tree控件不同),它包含SelectedItemChanged事件,用来监视树形结构中选中节点的变化。
TreeViewItem控件具有展开(Expanded)事件和收拢(Collapsed)事件,通过这两个事件可以监视节点的展开和收拢,并给出相应的处理。
在TextReader实例中,要显示目录和文件结构,需要用一种典型的树状结构,所以TreeView控件是首选。本例通过以下思路来完成目录的动态加载:
(1)文件系统中的目录和文件都作为TreeView控件中的节点,用TreeViewItem空间表示,而目录和文件的详细路径则保存在TreeViewItem.Tag属性中。
(2)在窗体启动时加载操作系统中所有的逻辑分区(例如,C:\、D:\等),实际上它们都是目录。
(3)监视树中节点的Expanded事件,如果是一个目录第一次展开,则加载该目录下直接的所有子目录和文件,不包括子目录的子目录和文件。
(4)监视TreeView控件的SelectedItemChanged事件,并根据当前选中节点的路径获取目录或文件的详细属性,并显示到界面上。
(5)当双击TreeView控件中的节点时,如果节点是文件,则判断文件类型;如果节点是文本格式文件,则将文本内容加载到界面上。
示例代码9-18是TextReader中与TreeView控件有关的代码,其中LoadLogicDrive()方法将系统中的逻辑分区信息加载到TreeView控件中,LoadDicTree()方法则将选中目录中的子目录和文件加载到该目录节点下。Dic_Expanded()是所有目录节点的Expanded事件处理函数,它首先判断该目录是不是第一次展开,如果是则加载该目录下的信息,否则不加载。
示例代码9-18:
namespace FileViewer{/// <summary>/// Window1.xaml 的交互逻辑/// </summary>public partial class WndMain : Window{public WndMain( ){InitializeComponent( );}
/// <summary>/// 加载指定目录下的文件和目录/// </summary>/// <param name="tv">要展开的目录</param>/// <returns>true则表示加载成功</returns>private bool LoadDicTree(TreeViewItem tvi){tvi.Items.Clear( ); //清除原有的所有节点(第一次展开标记) //获取目录路径string dicStr = ((string) tvi.Tag).Trim( );if (Directory.Exists(dicStr)) //如果目录存在{//获取目录信息DirectoryInfo dicInfo = new DirectoryInfo(dicStr);//遍历目录中所有子目录foreach (DirectoryInfo item in dicInfo.GetDirectories()){//如果为系统目录,则不显示到界面if ((item.Attributes & FileAttributes.System) == FileAttributes.System)continue;//创建TreeViewItem对象TreeViewItem tviDic = new TreeViewItem( );//保存目录路径到Tag属性tviDic.Tag = item.FullName;//设置节点显示文本tviDic.Header = item.Name;//节点添加一个子节点"tmp"作为第一次展开标记tviDic.Items.Add("tmp");//添加节点Expanded事件处理函数tvi.Expanded += new RoutedEventHandler(this.Dic_Expanded);//将节点添加到该父目录下tvi.Items.Add(tviDic);}//遍历目录中所有子文件foreach (FileInfo item in dicInfo.GetFiles()){//创建TreeViewItem对象TreeViewItem tviFile = new TreeViewItem( );//保存文件路径到Tag属性tviFile.Tag = item.FullName;//设置节点显示文本tviFile.Header = item.Name;//将节点添加到父目录下tvi.Items.Add(tviFile);}return true;}else //目录不存在,不处理{return false;}}
//加载系统中逻辑分区信息到目录树private void LoadLogicDrive( ){//遍历所有逻辑分区foreach (string drv in Directory.GetLogicalDrives()){//创建TreeViewItem对象TreeViewItem tvi = new TreeViewItem( );//将分区路径保存到Tag属性 tvi.Tag = drv;//设置节点显示文本tvi.Header = drv;//添加节点Expanded事件处理函数tvi.Expanded += new RoutedEventHandler(this.Dic_Expanded);//是目录,则添加"tmp"字符串子节点,用作第一次展开标记tvi.Items.Add("tmp"); //将节点添加到目录树this.tvDic.Items.Add(tvi); }}
//窗体加载事件处理函数private void Window_Loaded(object sender, RoutedEventArgs e){this.tvDic.Items.Clear( ); //清除目录树中所有节点this.LoadLogicDrive( ); //加载操作系统中所有逻辑分区}
//节点展开事件处理函数void Dic_Expanded(object sender, RoutedEventArgs e){//获取展开的节点TreeViewItem tvi = (TreeViewItem) e.Source;if (tvi.Tag == null) //如果节点不带有Tag数据,则返回{return;}if ((tvi.Items.Count == 1) && //如果节点Tag数据是string类型且为"tmp"(tvi.Items[0] is string) && //则是第一次展开,则加载子目录等信息到树形结构中((string) tvi.Items[0] == "tmp")){this.LoadDicTree(tvi); //加载目录的子目录和文件}}
//选中文件或目录发生变化事件处理函数privatevoidtvDic_SelectedItemChanged(objectsender,RoutedPropertyChangedEventArgs <object> e){//获取该节点的路径string dicStr = (string)((TreeViewItem) this.tvDic.SelectedItem).Tag;if (Directory.Exists(dicStr)) //是一个目录{//显示属性面板this.tabView.Visibility = Visibility.Visible;//获取目录信息DirectoryInfo dicInfo = new DirectoryInfo(dicStr);string hint = ""; //生成目录属性文本hint += string.Format("目 录: {0}\n", dicInfo.Name);hint += string.Format("路 径 {0}\n", dicInfo.FullName);hint += string.Format("根 目 录: {0}\n", dicInfo.Root);hint += string.Format("父 目 录: {0}\n", dicInfo.Parent);hint += string.Format("子 目 录 数: {0}\n", dicInfo.GetDirectories( ).Length);hint += string.Format("文 件 数: {0}\n", dicInfo.GetFiles( ).Length);hint += string.Format("创 建 时 间: {0}\n", dicInfo.CreationTime);hint += string.Format("最近访问时间: {0}\n", dicInfo.LastAccessTime);hint += string.Format("最近修改时间: {0}\n", dicInfo.LastWriteTime);hint += string.Format("目 录 属 性: {0}\n", dicInfo.Attributes);this.tbProp.Text = hint; //显示目录属性到界面}else if (File.Exists(dicStr)) //是一个文件{//显示属性面板this.tabView.Visibility = Visibility.Visible;//获取文件属性FileInfo fileInfo = new FileInfo(dicStr);string hint = ""; //生成文件属性文本hint += string.Format("文 件 名: {0}\n", fileInfo.Name);hint += string.Format("完 整 路 径: {0}\n", fileInfo.FullName);hint += string.Format("扩 展 名: {0}\n", fileInfo.Extension);hint += string.Format("父 目 录: {0}\n", fileInfo.Directory);hint += string.Format("创 建 时 间: {0}\n", fileInfo.CreationTime);hint += string.Format("最近访问时间: {0}\n", fileInfo.LastAccessTime);hint += string.Format("最近修改时间: {0}\n", fileInfo.LastWriteTime);hint += string.Format("文 件 属 性: {0}\n", fileInfo.Attributes);this.tbProp.Text = hint; //显示文件属性到界面}else{ //不是文件也不是目录,隐藏属性面板this.tabView.Visibility = Visibility.Hidden;}}
//目录树双击事件处理函数private void tvDic_MouseDoubleClick(object sender, MouseButtonEventArgs e){//获取双击发生的节点TreeViewItem tvi = (TreeViewItem) this.tvDic.SelectedItem;
if (tvi == null) //如果节点为空,返回{return;}
if (tvi.Items.Count > 0) //是目录,不是文件,返回{return;}
string fileName = (string) tvi.Tag; //获取文件名if (!File.Exists(fileName)) //文件不存在,返回{return;} //获取文件信息FileInfo fInfo = new FileInfo(fileName);//根据后缀名判断是否为文本格式的文件switch (fInfo.Extension.ToUpper( )) {case ".TXT": //文本文件case ".LOG": //日志文件case ".INI": //ini配置信息case ".XML": //xml文件case ".XAML": //xaml代码文件case ".BAT": //批处理文件case ".CPP": //C++代码文件case ".C": //C代码文件case ".H": //C、C++头文件case ".CS": //C#代码文件case ".VB": //VB代码文件case ".HTML": //Html网页代码文件case ".ASPX": //ASP.NET代码文件case ".VBS": //VBScript代码文件case ".JS": //JavaScript代码文件case ".CSS": //CSS格式定义文件case ".SLN": //VS解决方案文件this.ViewTxtFile(fileName); //加载文本文件到界面上break;case ".RTF":this.ViewRtfFile(fileName); //加载rtf文件到界面上break;default://提示不支持的文件格式MessageBox.Show("暂时还不支持该类型文件查看!", "提示",MessageBoxButton.OK, MessageBoxImage.Information);break;}}}}
实例TextReader中目录树的运行效果如图9-13所示,其中,界面左边是目录树,没有展开的目录也没有加载任何信息,只有在第一次展开之后才会加载具体的目录信息。界面右边的属性页面显示了当前选中文件或目录的详细属性,通过代码中的tvDic_SelectedItem Changed()方法实现。
(点击查看大图)图9-13 TextReader目录树运行效果
技巧:在实例TextReader中,目录树加载之所以分目录进行加载,主要是为了提高效率,一次性加载所有目录信息需要等待很长时间,而且并不是所有目录信息都会用到,真正使用的其实是很少的一部分。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询