【发布时间】:2015-10-16 20:41:44
【问题描述】:
我已经构建了一个在 winforms 中生成树视图的函数。它包括带有递归的子文件夹和文件。现在我想把它翻译成 wpf。
我无法弄清楚如何处理这些课程。我知道我必须创建自己的自定义类“treenode”,它具有类似于 winforms treenode 的属性“parent”。
但是在 wpf 中,我需要两种不同类型的树节点,以便我可以按数据类型正确绑定 wpf。我在 wpf 中有一个使用家庭的工作示例,我只是不确定如何将我的 winform 版本翻译成 wpf。有人可以帮我让我的 winform 版本在 wpf 中工作吗?
然后最终目标是让我在 WPF 中的树视图使用我的 winforms 示例中看到的目录和文件进行填充。然而,WPF 版本的样式应该保持文件和文件夹的“图标”显示。
我希望有人可以帮助我使其正常工作。欢迎任何建议和cmets。
ViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Linq;
namespace WpfApplication1
{
public class ViewModel : ObservableObject
{
// Properties
private ObservableCollection<DirectoryNode> directoryNodes;
public ObservableCollection<DirectoryNode> DirectoryNodes
{
get { return directoryNodes; }
set
{
directoryNodes = value;
NotifyPropertyChanged("DirectoryNodes");
}
}
private ObservableCollection<string> formats;
public ObservableCollection<string> Formats
{
get { return formats; }
set
{
formats = value;
NotifyPropertyChanged("Formats");
}
}
private ObservableCollection<string> directories;
public ObservableCollection<string> Directories
{
get { return directories; }
set
{
directories = value;
NotifyPropertyChanged("Directories");
}
}
// Creating data for testings
public ViewModel()
{
Formats = new ObservableCollection<string>();
Directories = new ObservableCollection<string>();
DirectoryNodes = new ObservableCollection<DirectoryNode>();
// create some dummy test data, eventually will be push to GUI
Formats.Add(".txt");
Formats.Add(".png");
Directories.Add(System.Environment.GetEnvironmentVariable("USERPROFILE"));
PopulateTree(Directories);
}
// Functions
static bool IsValidFileFormat(string filename, ObservableCollection<string> formats)
{
if (formats.Count == 0) return true;
string ext = Path.GetExtension(filename);
bool results = formats.Any(fileType => fileType.Equals(ext, StringComparison.OrdinalIgnoreCase));
return results;
}
public static DirectoryNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
DirectoryNode directoryNode = new DirectoryNode(){Filename=directoryInfo.Name};
foreach (var directory in directoryInfo.GetDirectories())
{
try
{
directoryNode.Children.Add(CreateDirectoryNode(directory));
}
catch (UnauthorizedAccessException) { }
}
foreach (var file in directoryInfo.GetFiles())
{
if (IsValidFileFormat(file.FullName, Formats))
{
FileNode node = new FileNode() { Filename = file.FullName };
directoryNode.Children.Add(node);
}
}
return directoryNode;
}
public void PopulateTree(ObservableCollection<string> directories)
{
foreach (string directoryPath in directories)
{
if (Directory.Exists(directoryPath))
{
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
DirectoryNodes.Add(CreateDirectoryNode(directoryInfo));
}
}
}
}
public class FileNode
{
public string Filepath { get; set; }
public string Filename { get; set; }
public DirectoryNode Parent { get; set; }
}
public class DirectoryNode
{
public string Filepath { get; set; }
public string Filename { get; set; }
public DirectoryNode Parent { get; set; }
public ObservableCollection<FileNode> Children { get; set; }
}
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
MainWindow.Xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="300"
WindowStartupLocation="CenterScreen">
<Window.DataContext>
<self:ViewModel/>
</Window.DataContext>
<Grid Margin="5">
<TreeView ItemsSource="{Binding Directories}" Grid.Row="1" Grid.ColumnSpan="2">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type self:DirectoryNode}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" FontFamily="WingDings" Content="1"/>
<TextBlock Text="{Binding Filename}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type self:FileNode}">
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" FontFamily="WingDings" Content="2"/>
<TextBlock Text="{Binding Filename}" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
工作 Winforms 示例
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Linq;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public static List<string> formats = new List<string>();
public Form1()
{
InitializeComponent();
//add userfolder
List<string> Directories = new List<string>();
Directories.Add(System.Environment.GetEnvironmentVariable("USERPROFILE"));
// get formats accepted
formats.Add(".txt");
formats.Add(".png");
PopulateTree(Directories, formats);
}
static bool IsValidFileFormat(string filename, List<string> formats)
{
if (formats.Count == 0) return true;
string ext = Path.GetExtension(filename);
bool results = formats.Any(fileType => fileType.Equals(ext, StringComparison.OrdinalIgnoreCase));
return results;
}
public static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
TreeNode directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
try
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
catch (UnauthorizedAccessException) { }
}
foreach (var file in directoryInfo.GetFiles())
{
if (IsValidFileFormat(file.FullName, formats))
{
TreeNode node = new TreeNode(file.FullName);
node.ForeColor = Color.Red;
directoryNode.Nodes.Add(node);
}
}
return directoryNode;
}
public void PopulateTree(List<string> directories, List<string> formats)
{
// main collection of nodes which are used to populate treeview
List<TreeNode> treeNodes = new List<TreeNode>();
foreach (string directoryPath in directories)
{
if (Directory.Exists(directoryPath))
{
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
treeNodes.Add(CreateDirectoryNode(directoryInfo));
}
}
treeView1.Nodes.AddRange(treeNodes.ToArray());
}
}
}
【问题讨论】:
-
WPF 与 winform 有着根本的不同。在 WPF 中,您使用 data 进行操作,而不是无休止地修改 UI 元素并希望它能够以某种方式工作,这就是您在 winforms 中所做的。
-
只需将“家庭”相关数据更改为您想要的任何内容,并调整 XAML 以使用新属性。
-
添加了更多关于翻译成 wpf 的具体问题,见上文
-
would these classes work alright- 是的。如果需要,只有那个 DirectoryItem 应该有一个ObservableCollection<FileItem>以便在 TreeView 中显示目录中的文件。 -
好的,谢谢,如果你不介意,因为我会进行调整,所以我会更新帖子,希望你们能指导我一些方法,我想我会用 sn 来解决大部分问题-ps 的帮助。谢谢