Hi,
here is a new version:
In your code (CodeBehind of MainWindow) change:
private void Save_Click(object sender, RoutedEventArgs e)
{
if (myList.ItemsSource == null) return;
ConfigClass cfg = new ConfigClass(this.ini_file_root.Text);
List<string> ltForSave = new List<string>();
foreach (MyModel obj in myList.ItemsSource)
cfg.SetValue("ListText.Files", "TextActive", obj.Name, !obj.StatusForCheckBox);
cfg.Save();
}
and new version of config class (I include comment - uncomment functionality):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace ListTxt
{
/// <summary>class for ini files</summary>
public class ConfigClass
{
#region Fields
/// <summary>content of ini in xml</summary>
private XElement config = new XElement("config");
/// <summary>char for identification of comment, first char is default</summary>
private string CommentCharacters = ";";
/// <summary>regex to identify comment</summary>
private string regCommentStr = "";
private Regex regComment;
/// <summary>reges to identiy element</summary>
private Regex regEntry;
/// <summary>regex to identiy header</summary>
private Regex regCaption;
#endregion
#region constructors
/// <summary>empty constructor</summary>
public ConfigClass()
{
regCommentStr = @"(\s*[" + CommentCharacters + "](?<comment>.*))?";
regComment = new Regex(regCommentStr);
regEntry = new Regex(@"^[ \t]*(?<entry>([^=])+)=(?<value>([^=" + CommentCharacters + "])+)" + regCommentStr + "$");
regCaption = new Regex(@"^[ \t]*(\[(?<section>([^\]])+)\]){1}" + regCommentStr + "$");
}
/// <summary>constructor to read ini file</summary>
/// <param name="filename">name fo inifile</param>
public ConfigClass(string fileName) : this()
{
if (!File.Exists(fileName)) throw new IOException($"File {fileName} not found");
this.FileName = fileName;
LoadIniToXML();
}
#endregion
/// <summary>save ini file</summary>
/// <returns></returns>
public bool Save()
{
if (string.IsNullOrEmpty(this.FileName)) return false;
try { SaveXMLToIni(); }
catch (Exception ex) { throw new IOException($"error writing ini file {this.FileName}", ex); }
return true;
}
/// <summary>full file name</summary>
public string FileName { get; set; }
/// <summary>directory of file</summary>
public string Directory
{
get
{
if (System.IO.Directory.Exists(this.FileName)) return Path.GetDirectoryName(this.FileName);
return string.Empty;
}
}
/// <summary>comment entry</summary>
/// <param name="section">name of section (in [...])</param>
/// <param name="entry">name of entry in section</param>
/// <returns>true if entry was found in section</returns>
public bool CommentValue(string section, string entry)
{
var res = from en in (from sec in config.Elements() where sec.Attribute("name").Value == section select sec).Elements(entry) select en;
if (res.Count() != 1) return false;
res.First().Value = CommentCharacters[0] + res.First().Name.ToString() + "=" + res.First().Attribute("name").Value;
res.First().Name = "comment";
return true;
}
/// <summary>delete entry</summary>
/// <param name="section">name of section (in [...])</param>
/// <param name="Entry">name of entry in section</param>
/// <returns>true if entry was found and deleted</returns>
public bool DeleteValue(string section, string entry)
{
var res = from en in (from sec in config.Elements() where sec.Attribute("name").Value == section select sec).Elements(entry) select en;
if (res.Count() != 1) return false;
res.First().Remove();
return true;
}
/// <summary>read entry from section (! case sensitive)</summary>
/// <param name="section">name of section (in [...])</param>
/// <param name="entry">name of entry in section</param>
/// <returns>value of entry in section</returns>
public string GetValue(string section, string entry)
{
var res = from en in (from sec in config.Elements() where sec.Attribute("name").Value == section select sec).Elements(entry) select en;
if (res.Count() != 1) return string.Empty;
return res.First().Attribute("value").Value;
}
/// <summary>set value of entry in section.
/// if entry (and section) not exists, entry (and section) are added.</summary>
/// <param name="section">name of section (in [...])</param>
/// <param name="Entry">name of entry in section</param>
/// <param name="Value">value of entry in sections</param>
/// <param name="comment">true - comment netry, false - uncomment entry</param>
/// <returns>true if sucsessvully set</returns>
public bool SetValue(string section, string entry, string value, bool comment = false)
{
XElement xeSection;
var resSection = from sec in config.Elements() where sec.Attribute("name") != null && sec.Attribute("name").Value == section select sec;
if (resSection.Count() > 1) return false;
if (resSection.Count() == 0)
{
xeSection = new XElement("section");
xeSection.Add(new XAttribute("name", section));
config.Add(xeSection);
}
else
{
xeSection = resSection.First();
}
XElement xeEntry;
var resEntry = from en in xeSection.Elements(entry) where en.Attribute("value").Value == value select en;
if (resEntry.Count() > 1) return false;
if (resEntry.Count() == 0)
{
xeEntry = new XElement(entry);
xeEntry.Add(new XAttribute("value", value));
xeSection.Add(xeEntry);
}
else
{
xeEntry = resEntry.First();
xeEntry.Attribute("value").Value = value;
}
// comment attribute
XAttribute xaComment = xeEntry.Attribute("comment");
if (xaComment == null)
{
xaComment = new XAttribute("comment", "");
xeEntry.Add(xaComment);
}
xaComment.Value = comment.ToString();
return true;
}
/// <summary>read all entries (without comments) and values</summary>
/// <param name="section">name of section (in [...])</param>
/// <returns>Dictionary with entry name (Key) and value</returns>
public Dictionary<String, String> GetSection(string section)
{
var res = from sec in config.Elements() where sec.Attribute("name").Value == section select sec;
return (from en in res.Elements()
where en.Name != "comment"
select new { n = en.Name.ToString(), v = en.Attribute("value").Value })
.ToDictionary(a => a.n, a => a.v);
}
/// <summary>get all section names</summary>
/// <returns>list of section names</returns>
public List<String> GetAllSections() =>
(from sec in config.Elements() where sec.Name != "comment" select sec.Attribute("@name").Value).ToList();
private void LoadIniToXML()
{
XElement section = config;
using (StreamReader sr = new StreamReader(this.FileName))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
if (string.IsNullOrEmpty(line)) break;
Match mEntry = regEntry.Match(line);
Match mSection = regCaption.Match(line);
Match mComment = regComment.Match(line);
if (mSection.Success)
{
section = new XElement("section");
section.Add(new XAttribute("name", mSection.Groups["section"].Value.Trim()));
config.Add(section);
}
else if (mEntry.Success)
{
XElement xe;
if (CommentCharacters.Contains(mEntry.Groups["entry"].Value[0]))
{
xe = new XElement(mEntry.Groups["entry"].Value.Trim().Substring(1));
xe.Add(new XAttribute("comment", "True"));
}
else xe = new XElement(mEntry.Groups["entry"].Value.Trim());
xe.Add(new XAttribute("value", mEntry.Groups["value"].Value.Trim()));
section.Add(xe);
}
else if (mComment.Success)
{
XElement xe = new XElement("comment");
xe.Value = mComment.Groups["comment"].Value.Trim();
section.Add(xe);
}
}
}
}
private void SaveXMLToIni()
{
using (StreamWriter sw = new StreamWriter(this.FileName))
{
foreach (var item in config.Descendants())
{
switch (item.Name.ToString())
{
case "section":
sw.WriteLine($"[{item.Attribute("name").Value}]");
break;
case "comment":
sw.WriteLine((item.Value.Length == 0) ? string.Empty : CommentCharacters[0] + item.Value);
break;
default:
if (item.Attribute("comment") != null && item.Attribute("comment").Value == "True") sw.Write(CommentCharacters[0]);
sw.WriteLine($"{item.Name}={item.Attribute("value").Value}");
break;
}
}
}
}
/// <summary>export alle sections, entry, comments as XML</summary>
/// <returns>XML document</returns>
public XElement ExportToXElement() => config;
}
}