我正在尝试使用TreeNode(System.Windows.Forms.TreeNode)作为我的一个应用程序的用户设置。
if(treeView.SelectedNode != null)
{
Properties.Settings.Default.SelectedTreeNode = treeView.SelectedNode;
Properties.Settings.Default.Save();
}
然后在应用程序加载时,我正在尝试使用该设置
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= Properties.Settings.Default.SelectedTreeNode;
但是无论我做什么,Properties.Settings.Default.SelectedTreeNode
在我重新加载应用程序时始终为null。
我也尝试过仅使用Object并强制转换为TreeNode,但这也不起作用。
我真的不想为此使用字符串设置,并且希望尽可能使用TreeNode,但是如果没有办法使用TreeNode,则序列化的TreeNode将起作用。我只是不太了解序列化。
答案 0 :(得分:3)
即使可以在设置中存储TreeNode
,也不能将反序列化的节点分配给SelectedNode
的{{1}}属性。 TreeView
是引用类型,并且由于您从设置加载的实例与树中存在的实例不同,因此该分配没有任何意义,并且将不起作用。 Taw在comment中的b点已经提到过。
要保留设置中的选定节点,最好依靠字符串属性。您至少有两个选择:
TreeNode
属性Name
属性选项1-名称属性
每个FullPath
具有一个TreeNode
属性,可用于查找该节点。
在创建节点时为节点分配唯一键:
Name
保存数据时,将treeView1.Nodes.Add("key", "text");
存储在设置中。
要根据设置选择节点:
treeView1.SelectedNode.Name
选项2-FullPath属性
每个treeView1.SelectedNode = treeView1.Nodes.Find("some key", true).FirstOrDefault();
都有一个TreeNode
,它获取从根树节点到当前树节点的路径。
路径由必须是所有树节点的标签组成 从根树节点开始导航到该树节点。的 节点标签由在 包含以下内容的TreeView控件的PathSeparator属性 节点。
创建节点时,无需进行特殊设置。每个节点都有FullPath
。
保存数据时,将FullPath
存储在设置中。
要根据设置选择节点:
treeView1.SelectedNode.FullPath
在上面的代码中,treeView1.SelectedNode = treeView1.Nodes.FindByPath(@"path\to\the\node");
是一种扩展方法,您可以创建该扩展方法以按路径查找ndoe:
FindByPath
答案 1 :(得分:0)
这里发生的是对Save
方法的调用尝试序列化该节点,以便将其存储在User.config
文件中。如果检查此文件,则会发现该节点为空:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="..." >
<section name="SomeProject.Properties.Settings" type="..." allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<SomeProject.Properties.Settings>
<setting name="SelectedTreeNode" serializeAs="Xml">
<value /> <!-- The node was not serialized! -->
</setting>
</SomeProject.Properties.Settings>
</userSettings>
</configuration>
原因可能是Save
方法正在尝试使用XmlSerializer
类进行序列化,该类不遵守ISerializable
接口,这是为{{ 1}}类。在某些时候它会在内部爆炸,并吞下错误,而是留下一个空值。
要解决此问题,您可以使用适当的序列化方法(即格式化程序)对TreeNode
对象进行序列化。格式化程序尊重TreeNode
接口。然后,您可以将结果ISerializable
存储在设置中,以后再读取并将它具体化到节点中:
string
在应用程序加载时:
if (string.IsNullOrWhiteSpace(Properties.Settings.Default.SelectedTreeNode))
{
Properties.Settings.Default.SelectedTreeNode = SerializeNode(treeView.SelectedNode);
Properties.Settings.Default.Save();
}
序列化功能:
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= DeserializeNode(Properties.Settings.Default.SelectedTreeNode);
对于这个答案,我正在使用public string SerializeNode(TreeNode node)
{
var formatter = new SoapFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, node);
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
var serialized = reader.ReadToEnd();
return serialized;
}
}
}
public TreeNode DeserializeNode(string nodeString)
{
var formatter = new SoapFormatter();
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
writer.Write(nodeString);
writer.Flush();
stream.Position = 0;
var node = (TreeNode)formatter.Deserialize(stream);
return node;
}
}
}
类。您将需要添加对SoapFormatter
的引用。