Define model classes and use databinding to edit the model, then you can break the problem to the following pieces:
Defining a Model class containing a List<Resource>
and each Resource
having Title
and Content
.
Write some logic to load model from xml or save model to xml.
Write a piece of code to arrange UI and setup UI controls to use databinding to your mode.
Then you can easily Load data from xml, edit in the UI and Save data to xml.
Model classes
You can model classes like this:
public class Model
{
public List<Resource> Resources { get; set; }
}
public class Resource
{
public string Title { get; set; }
public string Content { get; set; }
}
Setting up UI
There are different approaches to dynamically show a collection of controls in a form. Here I'll show how you can do that using a DataGridView as well as a TableLayoutPanel:
DataGridView
TableLayoutPanel
Create DataGridView
var dg = new DataGridView();
dg.Dock = DockStyle.Fill;
dg.BorderStyle = BorderStyle.None;
dg.GridColor = Color.Black;
dg.AutoGenerateColumns = true;
dg.EditMode = DataGridViewEditMode.EditOnEnter;
dg.DataSource = model.Resources;
dg.DataBindingComplete += (o, a) =>
{
dg.RowHeadersVisible = dg.ColumnHeadersVisible = false;
dg.AllowUserToResizeColumns = false;
dg.AllowUserToResizeRows = false;
dg.BackgroundColor = SystemColors.Control;
dg.Columns[0].ReadOnly = true;
dg.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dg.Columns[0].DefaultCellStyle.ForeColor = Color.Black;
dg.Columns[0].DefaultCellStyle.BackColor = SystemColors.Control;
dg.Columns[0].DefaultCellStyle.SelectionForeColor = Color.Black;
dg.Columns[0].DefaultCellStyle.SelectionBackColor = SystemColors.Control;
dg.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
};
this.Controls.Add(dg);
Create TableLayoutPanel
var tlp = new TableLayoutPanel() { ColumnCount = 2, AutoSize = true };
tlp.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
tlp.SuspendLayout();
foreach (var resource in model.Resources)
{
tlp.RowStyles.Add(new RowStyle(SizeType.AutoSize));
var lbl = new Label() { AutoSize = true, Margin = new Padding(4) };
lbl.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
lbl.DataBindings.Add(new Binding(nameof(Label.Text), resource, nameof(Resource.Title)));
var txt = new TextBox();
txt.DataBindings.Add(new Binding(nameof(TextBox.Text), resource, nameof(Resource.Content)));
txt.Dock = DockStyle.Fill;
tlp.Controls.AddRange(new Control[] { lbl, txt });
}
tlp.ResumeLayout();
this.Controls.Add(tlp);
Load and Save Model
You can create a class like this:
public class ModelFactory
{
public Model FromXmlString(string xml)
{
return new Model()
{
Resources = XElement.Parse(xml).Elements()
.Select(x => ResourceFromXElement(x)).ToList()
};
}
public string ToXmlString(Model model)
{
return new XElement("resources",
model.Resources.Select(x => ResourceToXElement(x)).ToArray())
.ToString();
}
private Resource ResourceFromXElement(XElement element)
{
return new Resource()
{
Title = element.Attribute("name").Value,
Content = element.Value
};
}
private XElement ResourceToXElement(Resource resource)
{
return new XElement("string",
new XAttribute("name", resource.Title),
resource.Content);
}
}
Then easily load and save model:
Model model;
ModelFactory modelFactory = new ModelFactory();
private void loadButton_Click(object sender, EventArgs e)
{
var xml = @"
<resources>
<string name=""name"">Tap Crush</string>
<string name=""mode"">Slow</string>
<string name=""score"">12345</string>
</resources>";
//Load model from xml
model = modelFactory.FromXmlString(xml);
//Setup UI
}
private void saveButton_Click(object sender, EventArgs e)
{
//Save model to xml
var xml = modelFactory.ToXmlString(model);
MessageBox.Show(xml);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…