Using a TreeNode as a User Setting
I'm trying to use a TreeNode (System.Windows.Forms.TreeNode) as a user setting for one of my applications.
if(treeView.SelectedNode != null)
{
Properties.Settings.Default.SelectedTreeNode = treeView.SelectedNode;
Properties.Settings.Default.Save();
}
Then on Application Load I'm trying to use that Setting
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= Properties.Settings.Default.SelectedTreeNode;
but no matter what I do, Properties.Settings.Default.SelectedTreeNode
is always null when I reload the application.
I've also tried just using an Object and casting to a TreeNode, but that doesn't work either.
I really don't want to use string Settings for this, and want to stick with TreeNode if possible, but a serialized TreeNode would work if there is no way to use a TreeNode. I'm just not too familiar with Serialization.
c# winforms
add a comment |
I'm trying to use a TreeNode (System.Windows.Forms.TreeNode) as a user setting for one of my applications.
if(treeView.SelectedNode != null)
{
Properties.Settings.Default.SelectedTreeNode = treeView.SelectedNode;
Properties.Settings.Default.Save();
}
Then on Application Load I'm trying to use that Setting
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= Properties.Settings.Default.SelectedTreeNode;
but no matter what I do, Properties.Settings.Default.SelectedTreeNode
is always null when I reload the application.
I've also tried just using an Object and casting to a TreeNode, but that doesn't work either.
I really don't want to use string Settings for this, and want to stick with TreeNode if possible, but a serialized TreeNode would work if there is no way to use a TreeNode. I'm just not too familiar with Serialization.
c# winforms
2
a) TreeNode actually is serializable but it doesn't come back in a restart. It does get stored while the app runs, though. I can't explain why that is so or how to workaround. color is not serializable but it works fine !? - b) do note that even if it came back it should still be a new copy of the node and your code should not select it in the tree, if that was actually what you meant. If you want to add it to the treeview along with labels and childnodes you will have to write code for that..!
– TaW
Nov 14 '18 at 22:40
1
So you do not, as you wrote, want to store a TreeNode itself, with all its chil nodes, tags etc.. but only a reliable way to select that node.. Quite misleading question!
– TaW
Nov 16 '18 at 13:03
add a comment |
I'm trying to use a TreeNode (System.Windows.Forms.TreeNode) as a user setting for one of my applications.
if(treeView.SelectedNode != null)
{
Properties.Settings.Default.SelectedTreeNode = treeView.SelectedNode;
Properties.Settings.Default.Save();
}
Then on Application Load I'm trying to use that Setting
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= Properties.Settings.Default.SelectedTreeNode;
but no matter what I do, Properties.Settings.Default.SelectedTreeNode
is always null when I reload the application.
I've also tried just using an Object and casting to a TreeNode, but that doesn't work either.
I really don't want to use string Settings for this, and want to stick with TreeNode if possible, but a serialized TreeNode would work if there is no way to use a TreeNode. I'm just not too familiar with Serialization.
c# winforms
I'm trying to use a TreeNode (System.Windows.Forms.TreeNode) as a user setting for one of my applications.
if(treeView.SelectedNode != null)
{
Properties.Settings.Default.SelectedTreeNode = treeView.SelectedNode;
Properties.Settings.Default.Save();
}
Then on Application Load I'm trying to use that Setting
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= Properties.Settings.Default.SelectedTreeNode;
but no matter what I do, Properties.Settings.Default.SelectedTreeNode
is always null when I reload the application.
I've also tried just using an Object and casting to a TreeNode, but that doesn't work either.
I really don't want to use string Settings for this, and want to stick with TreeNode if possible, but a serialized TreeNode would work if there is no way to use a TreeNode. I'm just not too familiar with Serialization.
c# winforms
c# winforms
edited Nov 16 '18 at 13:02
TaW
41.4k62864
41.4k62864
asked Nov 14 '18 at 20:57
John GrabanskiJohn Grabanski
294515
294515
2
a) TreeNode actually is serializable but it doesn't come back in a restart. It does get stored while the app runs, though. I can't explain why that is so or how to workaround. color is not serializable but it works fine !? - b) do note that even if it came back it should still be a new copy of the node and your code should not select it in the tree, if that was actually what you meant. If you want to add it to the treeview along with labels and childnodes you will have to write code for that..!
– TaW
Nov 14 '18 at 22:40
1
So you do not, as you wrote, want to store a TreeNode itself, with all its chil nodes, tags etc.. but only a reliable way to select that node.. Quite misleading question!
– TaW
Nov 16 '18 at 13:03
add a comment |
2
a) TreeNode actually is serializable but it doesn't come back in a restart. It does get stored while the app runs, though. I can't explain why that is so or how to workaround. color is not serializable but it works fine !? - b) do note that even if it came back it should still be a new copy of the node and your code should not select it in the tree, if that was actually what you meant. If you want to add it to the treeview along with labels and childnodes you will have to write code for that..!
– TaW
Nov 14 '18 at 22:40
1
So you do not, as you wrote, want to store a TreeNode itself, with all its chil nodes, tags etc.. but only a reliable way to select that node.. Quite misleading question!
– TaW
Nov 16 '18 at 13:03
2
2
a) TreeNode actually is serializable but it doesn't come back in a restart. It does get stored while the app runs, though. I can't explain why that is so or how to workaround. color is not serializable but it works fine !? - b) do note that even if it came back it should still be a new copy of the node and your code should not select it in the tree, if that was actually what you meant. If you want to add it to the treeview along with labels and childnodes you will have to write code for that..!
– TaW
Nov 14 '18 at 22:40
a) TreeNode actually is serializable but it doesn't come back in a restart. It does get stored while the app runs, though. I can't explain why that is so or how to workaround. color is not serializable but it works fine !? - b) do note that even if it came back it should still be a new copy of the node and your code should not select it in the tree, if that was actually what you meant. If you want to add it to the treeview along with labels and childnodes you will have to write code for that..!
– TaW
Nov 14 '18 at 22:40
1
1
So you do not, as you wrote, want to store a TreeNode itself, with all its chil nodes, tags etc.. but only a reliable way to select that node.. Quite misleading question!
– TaW
Nov 16 '18 at 13:03
So you do not, as you wrote, want to store a TreeNode itself, with all its chil nodes, tags etc.. but only a reliable way to select that node.. Quite misleading question!
– TaW
Nov 16 '18 at 13:03
add a comment |
2 Answers
2
active
oldest
votes
Even if you could store TreeNode
in settings, you cannot assign deserialized node to SelectedNode
property of TreeView
. TreeNode
is reference type and since the instance which you load from setting is not the same instance which exists in the tree, the assignment doesn't make sense and will not work. It's already mentioned in point b in the comment by Taw.
To preserve selected node in settings, it's better to rely on a string property. You have at least two options:
- Store
Name
property of the node in settings - Store
FullPath
property of the node in settings
Option 1 - Name Property
Each TreeNode
has a Name
property which can be used to find the node.
Assign a unique key to nodes when creating them:
treeView1.Nodes.Add("key", "text");
When saving data, store
treeView1.SelectedNode.Name
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.Find("some key", true).FirstOrDefault();
Option 2 - FullPath Property
Each TreeNode
has a FullPath
which gets the path from the root tree node to the current tree node.
The path consists of the labels of all the tree nodes that must be
navigated to reach this tree node, starting at the root tree node. The
node labels are separated by the delimiter character specified in the
PathSeparator property of the TreeView control that contains this
node.
When creating node, you don't need to do special settings. Every node has
FullPath
.When saving data, store
treeView1.SelectedNode.FullPath
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.FindByPath(@"pathtothenode");
In above code, FindByPath
is an extension method which you can create to find the ndoe by path:
using System.Windows.Forms;
public static class TreeViewExtensiona
{
public static TreeNode FindByPath(this TreeNodeCollection nodes, string path)
{
TreeNode found = null;
foreach (TreeNode n in nodes)
{
if (n.FullPath == path)
found = n;
else
found = FindByPath(n.Nodes, path);
if (found != null)
return found;
}
return null;
}
}
1
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
1
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
add a comment |
What's happening here is that the call to the Save
method attempts to serialize the node in order to store it in the User.config
file. If you inspect this file, you will find that the node is empty:
<?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>
The reason is probably that the Save
method is attempting the serialization using the XmlSerializer
class, which does not respect the ISerializable
interface, which is how serialization is implemented for the TreeNode
class. It blows up internally at some point and it swallows the error, leaving an empty value instead.
What you can do to get around this is serialize the TreeNode
object using a proper serialization method, which is a formatter. Formatters respect the ISerializable
interface. You can then store the resulting string
in the setting and later read it and materialize it into the node:
if (string.IsNullOrWhiteSpace(Properties.Settings.Default.SelectedTreeNode))
{
Properties.Settings.Default.SelectedTreeNode = SerializeNode(treeView.SelectedNode);
Properties.Settings.Default.Save();
}
On application load:
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= DeserializeNode(Properties.Settings.Default.SelectedTreeNode);
The serialization functions:
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;
}
}
}
For this answer, I am using the SoapFormatter
class. You will need to add a reference to System.Runtime.Serialization.Formatters.Soap
.
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53308604%2fusing-a-treenode-as-a-user-setting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Even if you could store TreeNode
in settings, you cannot assign deserialized node to SelectedNode
property of TreeView
. TreeNode
is reference type and since the instance which you load from setting is not the same instance which exists in the tree, the assignment doesn't make sense and will not work. It's already mentioned in point b in the comment by Taw.
To preserve selected node in settings, it's better to rely on a string property. You have at least two options:
- Store
Name
property of the node in settings - Store
FullPath
property of the node in settings
Option 1 - Name Property
Each TreeNode
has a Name
property which can be used to find the node.
Assign a unique key to nodes when creating them:
treeView1.Nodes.Add("key", "text");
When saving data, store
treeView1.SelectedNode.Name
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.Find("some key", true).FirstOrDefault();
Option 2 - FullPath Property
Each TreeNode
has a FullPath
which gets the path from the root tree node to the current tree node.
The path consists of the labels of all the tree nodes that must be
navigated to reach this tree node, starting at the root tree node. The
node labels are separated by the delimiter character specified in the
PathSeparator property of the TreeView control that contains this
node.
When creating node, you don't need to do special settings. Every node has
FullPath
.When saving data, store
treeView1.SelectedNode.FullPath
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.FindByPath(@"pathtothenode");
In above code, FindByPath
is an extension method which you can create to find the ndoe by path:
using System.Windows.Forms;
public static class TreeViewExtensiona
{
public static TreeNode FindByPath(this TreeNodeCollection nodes, string path)
{
TreeNode found = null;
foreach (TreeNode n in nodes)
{
if (n.FullPath == path)
found = n;
else
found = FindByPath(n.Nodes, path);
if (found != null)
return found;
}
return null;
}
}
1
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
1
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
add a comment |
Even if you could store TreeNode
in settings, you cannot assign deserialized node to SelectedNode
property of TreeView
. TreeNode
is reference type and since the instance which you load from setting is not the same instance which exists in the tree, the assignment doesn't make sense and will not work. It's already mentioned in point b in the comment by Taw.
To preserve selected node in settings, it's better to rely on a string property. You have at least two options:
- Store
Name
property of the node in settings - Store
FullPath
property of the node in settings
Option 1 - Name Property
Each TreeNode
has a Name
property which can be used to find the node.
Assign a unique key to nodes when creating them:
treeView1.Nodes.Add("key", "text");
When saving data, store
treeView1.SelectedNode.Name
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.Find("some key", true).FirstOrDefault();
Option 2 - FullPath Property
Each TreeNode
has a FullPath
which gets the path from the root tree node to the current tree node.
The path consists of the labels of all the tree nodes that must be
navigated to reach this tree node, starting at the root tree node. The
node labels are separated by the delimiter character specified in the
PathSeparator property of the TreeView control that contains this
node.
When creating node, you don't need to do special settings. Every node has
FullPath
.When saving data, store
treeView1.SelectedNode.FullPath
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.FindByPath(@"pathtothenode");
In above code, FindByPath
is an extension method which you can create to find the ndoe by path:
using System.Windows.Forms;
public static class TreeViewExtensiona
{
public static TreeNode FindByPath(this TreeNodeCollection nodes, string path)
{
TreeNode found = null;
foreach (TreeNode n in nodes)
{
if (n.FullPath == path)
found = n;
else
found = FindByPath(n.Nodes, path);
if (found != null)
return found;
}
return null;
}
}
1
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
1
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
add a comment |
Even if you could store TreeNode
in settings, you cannot assign deserialized node to SelectedNode
property of TreeView
. TreeNode
is reference type and since the instance which you load from setting is not the same instance which exists in the tree, the assignment doesn't make sense and will not work. It's already mentioned in point b in the comment by Taw.
To preserve selected node in settings, it's better to rely on a string property. You have at least two options:
- Store
Name
property of the node in settings - Store
FullPath
property of the node in settings
Option 1 - Name Property
Each TreeNode
has a Name
property which can be used to find the node.
Assign a unique key to nodes when creating them:
treeView1.Nodes.Add("key", "text");
When saving data, store
treeView1.SelectedNode.Name
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.Find("some key", true).FirstOrDefault();
Option 2 - FullPath Property
Each TreeNode
has a FullPath
which gets the path from the root tree node to the current tree node.
The path consists of the labels of all the tree nodes that must be
navigated to reach this tree node, starting at the root tree node. The
node labels are separated by the delimiter character specified in the
PathSeparator property of the TreeView control that contains this
node.
When creating node, you don't need to do special settings. Every node has
FullPath
.When saving data, store
treeView1.SelectedNode.FullPath
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.FindByPath(@"pathtothenode");
In above code, FindByPath
is an extension method which you can create to find the ndoe by path:
using System.Windows.Forms;
public static class TreeViewExtensiona
{
public static TreeNode FindByPath(this TreeNodeCollection nodes, string path)
{
TreeNode found = null;
foreach (TreeNode n in nodes)
{
if (n.FullPath == path)
found = n;
else
found = FindByPath(n.Nodes, path);
if (found != null)
return found;
}
return null;
}
}
Even if you could store TreeNode
in settings, you cannot assign deserialized node to SelectedNode
property of TreeView
. TreeNode
is reference type and since the instance which you load from setting is not the same instance which exists in the tree, the assignment doesn't make sense and will not work. It's already mentioned in point b in the comment by Taw.
To preserve selected node in settings, it's better to rely on a string property. You have at least two options:
- Store
Name
property of the node in settings - Store
FullPath
property of the node in settings
Option 1 - Name Property
Each TreeNode
has a Name
property which can be used to find the node.
Assign a unique key to nodes when creating them:
treeView1.Nodes.Add("key", "text");
When saving data, store
treeView1.SelectedNode.Name
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.Find("some key", true).FirstOrDefault();
Option 2 - FullPath Property
Each TreeNode
has a FullPath
which gets the path from the root tree node to the current tree node.
The path consists of the labels of all the tree nodes that must be
navigated to reach this tree node, starting at the root tree node. The
node labels are separated by the delimiter character specified in the
PathSeparator property of the TreeView control that contains this
node.
When creating node, you don't need to do special settings. Every node has
FullPath
.When saving data, store
treeView1.SelectedNode.FullPath
in settings.
To select the node based on the settings:
treeView1.SelectedNode = treeView1.Nodes.FindByPath(@"pathtothenode");
In above code, FindByPath
is an extension method which you can create to find the ndoe by path:
using System.Windows.Forms;
public static class TreeViewExtensiona
{
public static TreeNode FindByPath(this TreeNodeCollection nodes, string path)
{
TreeNode found = null;
foreach (TreeNode n in nodes)
{
if (n.FullPath == path)
found = n;
else
found = FindByPath(n.Nodes, path);
if (found != null)
return found;
}
return null;
}
}
edited Nov 15 '18 at 0:22
answered Nov 15 '18 at 0:15
Reza AghaeiReza Aghaei
67.2k856167
67.2k856167
1
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
1
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
add a comment |
1
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
1
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
1
1
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
I used Option 2 here. I feel FullPath is exactly what I wanted, and the FIndByPath extension is very simple.
– John Grabanski
Nov 15 '18 at 13:49
1
1
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
plus1 for mindreading :-) The other answer is quite useful when one actually wants to store a treenode.
– TaW
Nov 16 '18 at 13:06
add a comment |
What's happening here is that the call to the Save
method attempts to serialize the node in order to store it in the User.config
file. If you inspect this file, you will find that the node is empty:
<?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>
The reason is probably that the Save
method is attempting the serialization using the XmlSerializer
class, which does not respect the ISerializable
interface, which is how serialization is implemented for the TreeNode
class. It blows up internally at some point and it swallows the error, leaving an empty value instead.
What you can do to get around this is serialize the TreeNode
object using a proper serialization method, which is a formatter. Formatters respect the ISerializable
interface. You can then store the resulting string
in the setting and later read it and materialize it into the node:
if (string.IsNullOrWhiteSpace(Properties.Settings.Default.SelectedTreeNode))
{
Properties.Settings.Default.SelectedTreeNode = SerializeNode(treeView.SelectedNode);
Properties.Settings.Default.Save();
}
On application load:
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= DeserializeNode(Properties.Settings.Default.SelectedTreeNode);
The serialization functions:
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;
}
}
}
For this answer, I am using the SoapFormatter
class. You will need to add a reference to System.Runtime.Serialization.Formatters.Soap
.
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
add a comment |
What's happening here is that the call to the Save
method attempts to serialize the node in order to store it in the User.config
file. If you inspect this file, you will find that the node is empty:
<?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>
The reason is probably that the Save
method is attempting the serialization using the XmlSerializer
class, which does not respect the ISerializable
interface, which is how serialization is implemented for the TreeNode
class. It blows up internally at some point and it swallows the error, leaving an empty value instead.
What you can do to get around this is serialize the TreeNode
object using a proper serialization method, which is a formatter. Formatters respect the ISerializable
interface. You can then store the resulting string
in the setting and later read it and materialize it into the node:
if (string.IsNullOrWhiteSpace(Properties.Settings.Default.SelectedTreeNode))
{
Properties.Settings.Default.SelectedTreeNode = SerializeNode(treeView.SelectedNode);
Properties.Settings.Default.Save();
}
On application load:
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= DeserializeNode(Properties.Settings.Default.SelectedTreeNode);
The serialization functions:
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;
}
}
}
For this answer, I am using the SoapFormatter
class. You will need to add a reference to System.Runtime.Serialization.Formatters.Soap
.
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
add a comment |
What's happening here is that the call to the Save
method attempts to serialize the node in order to store it in the User.config
file. If you inspect this file, you will find that the node is empty:
<?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>
The reason is probably that the Save
method is attempting the serialization using the XmlSerializer
class, which does not respect the ISerializable
interface, which is how serialization is implemented for the TreeNode
class. It blows up internally at some point and it swallows the error, leaving an empty value instead.
What you can do to get around this is serialize the TreeNode
object using a proper serialization method, which is a formatter. Formatters respect the ISerializable
interface. You can then store the resulting string
in the setting and later read it and materialize it into the node:
if (string.IsNullOrWhiteSpace(Properties.Settings.Default.SelectedTreeNode))
{
Properties.Settings.Default.SelectedTreeNode = SerializeNode(treeView.SelectedNode);
Properties.Settings.Default.Save();
}
On application load:
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= DeserializeNode(Properties.Settings.Default.SelectedTreeNode);
The serialization functions:
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;
}
}
}
For this answer, I am using the SoapFormatter
class. You will need to add a reference to System.Runtime.Serialization.Formatters.Soap
.
What's happening here is that the call to the Save
method attempts to serialize the node in order to store it in the User.config
file. If you inspect this file, you will find that the node is empty:
<?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>
The reason is probably that the Save
method is attempting the serialization using the XmlSerializer
class, which does not respect the ISerializable
interface, which is how serialization is implemented for the TreeNode
class. It blows up internally at some point and it swallows the error, leaving an empty value instead.
What you can do to get around this is serialize the TreeNode
object using a proper serialization method, which is a formatter. Formatters respect the ISerializable
interface. You can then store the resulting string
in the setting and later read it and materialize it into the node:
if (string.IsNullOrWhiteSpace(Properties.Settings.Default.SelectedTreeNode))
{
Properties.Settings.Default.SelectedTreeNode = SerializeNode(treeView.SelectedNode);
Properties.Settings.Default.Save();
}
On application load:
if (Properties.Settings.Default.SelectedTreeNode != null)
treeView.SelectedNode= DeserializeNode(Properties.Settings.Default.SelectedTreeNode);
The serialization functions:
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;
}
}
}
For this answer, I am using the SoapFormatter
class. You will need to add a reference to System.Runtime.Serialization.Formatters.Soap
.
edited Nov 15 '18 at 14:47
answered Nov 14 '18 at 22:55
JuanRJuanR
5,0901928
5,0901928
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
add a comment |
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Great answer to he question as written. Pitty it is not what ghe actually meant but may come useful to folks mislead by the question tile etc.. I wish I could upvote more than once..
– TaW
Nov 16 '18 at 13:05
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
Thank you, @TaW!
– JuanR
Nov 16 '18 at 14:09
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53308604%2fusing-a-treenode-as-a-user-setting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
a) TreeNode actually is serializable but it doesn't come back in a restart. It does get stored while the app runs, though. I can't explain why that is so or how to workaround. color is not serializable but it works fine !? - b) do note that even if it came back it should still be a new copy of the node and your code should not select it in the tree, if that was actually what you meant. If you want to add it to the treeview along with labels and childnodes you will have to write code for that..!
– TaW
Nov 14 '18 at 22:40
1
So you do not, as you wrote, want to store a TreeNode itself, with all its chil nodes, tags etc.. but only a reliable way to select that node.. Quite misleading question!
– TaW
Nov 16 '18 at 13:03