[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 266
  • Last Modified:

Persistent User Settings/Values

I'm trying to let a user set the path folders for my treeview at runtime.
I would like to try and duplicate Meta Browsers function to set the folders at run time and store them on application exit.

From what I can figure out is that Meta Browser lets a user choose paths that will be displayed in the treeview in somekind of datagrid and stores all the settings in a xml file.
I have tried to acomplish this in the settings.settings file but without any bigger succes.
The other idea I have is to add an xml file to the project and pull the folders from there, but then It's to hard for me to build a datagridview similar to Meta Browsers.

Any points to a close call solution ?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
 
namespace WindowsFormsApplication18
{
 
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //Create Title Node
            TreeNode booktitles = treeView1.Nodes.Add("Movies");
 
            //Add Locations
            string Location = @"\\Homeserver\Media\";
            DirectoryInfo dir = new DirectoryInfo(Location);
            AddNode(dir, booktitles);
            
            Location = @"\\Homeserver\Media 2\";
            dir = new DirectoryInfo(Location);
            AddNode(dir, booktitles);
 
            Location = @"\\Homeserver\Safe\";
            dir = new DirectoryInfo(Location);
            AddNode(dir, booktitles);
 
            Location = @"\\Homeserver\Safe2\";
            dir = new DirectoryInfo(Location);
            AddNode(dir, booktitles);
 
        }
 
 
 
        public void AddNode(DirectoryInfo dir, TreeNode node)
        {
            try
    {
            foreach (DirectoryInfo dInfo in dir.GetDirectories())
            {
                TreeNode mainNext = node.Nodes.Add(dInfo.Name);
                AddNode(dInfo, mainNext);
                mainNext.ToolTipText = dInfo.FullName;
            }
    }
            catch (UnauthorizedAccessException)
            {
                node.Nodes.Add("Access denied");
            }
 
            // Catch other exceptions
            catch (Exception)
            {
                node.Nodes.Add("Error accessing directory!");
            }
 
 
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show();
        }
 
 
 
    }
}

Open in new window

folders.jpg
metabrowserxml.jpg
0
Smyken
Asked:
Smyken
  • 10
  • 5
1 Solution
 
wht1986Commented:
What I typically do is create a typed dataset in  my project where the table schema matches whatever values i need to store.

For this example, Dataset1 is a dataset with a single data table called 'User' that has several columns.

            DataSet1 ds = new DataSet1();
           
            // add fluff data
            ds.Users.AddUsersRow("UserName1", "SomeSetting1");
            ds.Users.AddUsersRow("UserName2", "SomeSetting2");
           
            // save the xml file
            ds.WriteXml("path to my xml file");

            // read the xml file
            ds.ReadXml("path to my xml file");

of course do get the setting you want you can just iterate through the rows of the data table, etc  but this method sure beats creating xml by hand
0
 
wht1986Commented:
u can ever create the schema file by

            DataSet genericDataset = new DataSet();
            genericDataset.ReadXml("path to Meta Browser xml file");
            genericDataset.WriteXmlSchema("name of the xsd file you want");

now you can add the generated xsd file to the project so you have easy to access typed dataset intellisense goodness
0
 
SmykenAuthor Commented:
I'm sorry wht1986 but that is a bit to hard for me to understand I'm a beginner.


I managed to add an xml file AMFOPTIONS.xml to the project and can now read the paths that are located there.

Now I just need a function to let the User Pick the Paths he want and save them to the <Location> Element in my AMFOPTIONS.xml and to delete if he wants to.
The Meta Browser Datagridview looks really like a nice and neat way to do it especially with that red remove button, any other suggestions or code examples how this could be done in a good way ?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;
 
namespace WindowsFormsApplication18
{
 
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //Create Title Node
            TreeNode booktitles = treeView1.Nodes.Add("Movies");
 
            XmlDocument doc = new XmlDocument();
            doc.Load("AMFOPTIONS.xml");
 
            XmlNodeList LocationList = doc.GetElementsByTagName("Location");
            
            //Load Paths From XML
            foreach (XmlNode node in LocationList)
            {
                XmlElement LocationElement = (XmlElement)node;
 
                string Location = LocationElement.InnerText;
                
               DirectoryInfo dir = new DirectoryInfo(Location);
               AddNode(dir, booktitles);
            } 
        }
 
 
 
        public void AddNode(DirectoryInfo dir, TreeNode node)
        {
            try
    {
            foreach (DirectoryInfo dInfo in dir.GetDirectories())
            {
                TreeNode mainNext = node.Nodes.Add(dInfo.Name);
                AddNode(dInfo, mainNext);
                mainNext.ToolTipText = dInfo.FullName;
            }
    }
            catch (UnauthorizedAccessException)
            {
                node.Nodes.Add("Access denied");
            }
 
            // Catch other exceptions
            catch (Exception)
            {
                node.Nodes.Add("Error accessing directory!");
            }
 
 
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show();
        }
 
 
 
    }
}

Open in new window

0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 
wht1986Commented:
Ok it looks like you are storing the main root paths in the Location element.  Then after load you are looping through and creating a root tree node.  for each of these nodes, you recursively query the filesystem and add child tree node for each sub directory.

Now out of the xml nodes stored in the location element, do you just need to flag some of them as selected based on the users preferences?

In this tree view is the user able to select any of the subdirectory nodes that you created dynamically to be saved in the xml file as well?
0
 
SmykenAuthor Commented:
The Treeview is just for display purpose of the contents of the folders.

When the application starts the Treeview will be empty becouse no Root folders have been choosen to display.

There for I need to let the user somehow specify the his Media/Root Folders to display, Meta Browsers way of using datagridview to save and delete main root paths looks like a good way to go.

Nothing from the treeview is used its only there for navigation through out the media library.

You may download and install Meta Browser and see what I mean, Im sorry for my bad explanations 8=(

http://themetabrowser.com/download/
0
 
wht1986Commented:
Ah I see, so there will be some other part of the user interface where the user will do the management. The adds and deletes from this UI element will basically add and remove nodes from the location list in the xml file.

I think the easiest thing to do would be in that management UI, query the location nodes like you did and build a list.  The user can add/remove from this list as needed. No changes to the xml file happen yet.

When the user clicks save, Find the <Locations> node and do a RemoveAll(), this will drop all the <Location> child nodes. Now loop through the UI list and add back only the items the user has left remaining as new <Location> nodes under the <Locations> parent node.
0
 
wht1986Commented:
Here's some basic code:

Get the Locations Node (there is only 1 i think so i used the [0] index from the array)

XmlNode locationsElement = doc.GetElementsByTagName("Locations")[0];

clear all the children

locationsElement .RemoveAll();

Add a new location element

XmlElement elem = doc.CreateElement("Location");
elem.InnerText=@"\\server\share";
locations.AppendChild(elem);

0
 
SmykenAuthor Commented:
Hmm I don't really get you.

Lets try this way, forget all the treeview and everything else.

I have a xml file that is structured like this:

<Options>
  <Locations>
    <Location>\\HOMESERVER\Media</Location>
    <Location>\\HOMESERVER\Media 2</Location>
    <Location>\\HOMESERVER\Safe</Location>
    <Location>\\HOMESERVER\Safe2</Location>
  </Locations>
</Options>

All I need is a way to open a folderbrowserdialog and pick a path and add it to the <Location></Location> Element and save.
Then have some easy way to read the locations from the xml and to phisicly see them and to be able to delete a <Location></Location> Element.
This is done really nice with the Datagridview controll in Meta Browser as you can see on the upper picture I provided.

I have managed to display/read the <Location></Location> Elements into a datagrid, like in the picture below by following a example I found on google.
Now I want to somehow add a delete button/image like on the above datagrid that would delete the selected <Location></Location> element,
and add a openfolderdialog button once again like in the above picture that would set the path for the <Location></Location> Element.



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace WindowsFormsApplication18
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            DataSet dsAuthors = new DataSet("authors");
 
            InitializeComponent();
            string filePath = "AMFOPTIONS.xml";
            dsAuthors.ReadXml(filePath);
            dataGrid1.DataSource = dsAuthors;
            dataGrid1.DataMember = "Location";
            //dataGrid1.Text = dataGrid1.DataMember;
        }
        
 
 
    }
}

Open in new window

datagrid-tryout.jpg
0
 
wht1986Commented:
Here's an example.  Quick form which lists the contents of the xml file.  You can add and remove from the list. Clicking save writes the results back to the xml file.

my xml file looks like:

<?xml version="1.0" standalone="yes"?>
<Options xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Locations>
    <Location>\\HOMESERVER\Media</Location>
    <Location>\\HOMESERVER\Media 2</Location>
    <Location>\\HOMESERVER\Safe</Location>
    <Location>\\HOMESERVER\Safe2</Location>
    <Location>C:\Users\Public</Location>
  </Locations>
</Options>
private void Form1_Load(object sender, EventArgs e)
{
    LoadFromXml();
}
 
private void LoadFromXml()
{
    XmlDocument doc = new XmlDocument();
    doc.Load(Application.StartupPath + "\\MyXmlFile.xml");
    
    XmlNodeList list = doc.GetElementsByTagName("Location");
    foreach (XmlNode node in list)
        this.listBox1.Items.Add(node.InnerText);
}
 
private void AddButton_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
        this.listBox1.Items.Add(this.folderBrowserDialog1.SelectedPath);
}
 
private void RemoveButton_Click(object sender, EventArgs e)
{
    this.listBox1.Items.RemoveAt(this.listBox1.SelectedIndex);
}
 
private void SaveButton_Click(object sender, EventArgs e)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(Application.StartupPath + "\\MyXmlFile.xml");
    XmlNode locationRoot = doc.GetElementsByTagName("Locations")[0];
    locationRoot.RemoveAll();
 
    foreach (string s in this.listBox1.Items)
    {
        XmlElement elem = doc.CreateElement("Location");
        elem.InnerText = s;
        locationRoot.AppendChild(elem);
    }
 
    doc.Save(Application.StartupPath + "\\MyXmlFile.xml");
}

Open in new window

0
 
wht1986Commented:
Hmm my picture didnt attach, let me try again
Capture.JPG
0
 
SmykenAuthor Commented:
Got it partially working.

I can add nodes,remove,save all fine.
But when I startup the form the listbox is empty even though there are Location elements.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
 
namespace WindowsFormsApplication19
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            LoadFromXml();
        }
 
        private void LoadFromXml()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(Application.StartupPath + "\\MyXmlFile.xml");
 
            XmlNodeList list = doc.GetElementsByTagName("Location");
            foreach (XmlNode node in list)
                this.listBox1.Items.Add(node.InnerText);
        }
 
        private void AddButton_Click(object sender, EventArgs e)
        {
            if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                this.listBox1.Items.Add(this.folderBrowserDialog1.SelectedPath);
        }
 
        private void RemoveButton_Click(object sender, EventArgs e)
        {
            this.listBox1.Items.RemoveAt(this.listBox1.SelectedIndex);
        }
 
        private void SaveButton_Click(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(Application.StartupPath + "\\MyXmlFile.xml");
            XmlNode locationRoot = doc.GetElementsByTagName("Locations")[0];
            locationRoot.RemoveAll();
 
            foreach (string s in this.listBox1.Items)
            {
                XmlElement elem = doc.CreateElement("Location");
                elem.InnerText = s;
                locationRoot.AppendChild(elem);
            }
 
            doc.Save(Application.StartupPath + "\\MyXmlFile.xml");
        }
 
    }
}
 
 
 
 
 
 
 
 
xml file:
 
<?xml version="1.0" standalone="yes"?>
<Options xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Locations>
    <Location>C:\Users\Public</Location>
    <Location>C:\Users\Cyprian\Desktop\Carbonite</Location>
    <Location>C:\Users\Cyprian\Desktop\c#</Location>
  </Locations>
</Options>

Open in new window

0
 
wht1986Commented:
replace the line with the name of your XML file

doc.Load(Application.StartupPath + "\\MyXmlFile.xml");
0
 
SmykenAuthor Commented:
Nevermind, had to move:

LoadFromXml();

to

public Form1()
        {
            InitializeComponent();
             LoadFromXml();

        }


working now somewhat the way I want.
Thanks for all the help ! All points to you !
0
 
wht1986Commented:
awesome, glad i could help
0
 
wht1986Commented:
Just out of curiosity, what could i have done more of to get the A rating above and beyond giving you working code?
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

  • 10
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now