Carregue o objeto do xml, edite os valores em uma IU dinâmica e salve de volta no xml

Jan 12 2021

Acabei de ler e aplicar ao objeto dinâmico no painel do contêiner, ao rótulo do título, à caixa de texto do conteúdo. mas aqui não consigo salvá-lo quando preencho os dados na caixa de texto.

este é o meu código xml de desserialização:

string Location= Path.Combine("D:\\Data\\Code.xml");
XmlDocument doc = new XmlDocument();
doc.Load(lokasiString);
foreach (XmlNode node in doc.DocumentElement)
{
    string name = node.Attributes[0].InnerXml;
    string value = node.InnerText;

    // create panel
    Panel panel = new Panel();
    panel.Name = "panelImages";
    panel.Size = new Size((int)(this.Width*0.9), 30);
    panel.Dock = DockStyle.Top;
    panel.BorderStyle = BorderStyle.FixedSingle;

    Label l = new Label();
    l.Text = name;
    l.Font = new Font("Serif", 12, FontStyle.Bold);
    l.ForeColor = Color.Black;
    l.Size = new Size((int)(this.Width * 0.2), 30);
    l.Dock = DockStyle.Left;    
    TextBox tb = new TextBox();
    tb.Text = value;
    tb.Font = new Font("Serif", 12, FontStyle.Bold);
    tb.ForeColor = Color.Black;
    tb.Size = new Size((int)(this.Width * 0.9), 30);
    tb.Dock = DockStyle.Left;

    panel.Controls.Add(tb);
    panel.Controls.Add(lt);
    panel.Controls.Add(l);    
    flowLayoutPanel1.Controls.Add(panel);
}

e este meu código Xml:

<resources>
    <string name="name">Tap Crush</string>
    <string name="mode">Slow</string>
    <string name="score">12345</string>
</resources>

Não tenho conhecimento prévio de análise de Xml com C #.

Respostas

2 RezaAghaei Jan 12 2021 at 03:11

Defina classes de modelo e use ligação de dados para editar o modelo, então você pode dividir o problema nas seguintes partes:

  1. Definindo uma classe de modelo contendo a List<Resource>e cada Resourcetendo Titlee Content.

  2. Escreva alguma lógica para carregar o modelo de xml ou salve o modelo em xml.

  3. Escreva um pedaço de código para organizar a IU e configurar os controles da IU para usar a ligação de dados em seu modo.

Então você pode facilmente carregar dados de xml, editar na IU e salvar dados em xml.

Aulas de modelo

Você pode modelar classes como esta:

public class Model
{
    public List<Resource> Resources { get; set; }
}
public class Resource
{
    public string Title { get; set; }
    public string Content { get; set; }
}

Configurando a IU

Existem diferentes abordagens para mostrar dinamicamente uma coleção de controles em um formulário. Aqui, mostrarei como você pode fazer isso usando um DataGridView, bem como um TableLayoutPanel:

DataGridView

TableLayoutPanel

Criar 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);

Criar 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);

Carregar e salvar o modelo

Você pode criar uma classe como esta:

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);
    }
}

Em seguida, carregue e salve facilmente o modelo:

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);
}