C# 用户窗体上的动态按钮

C# 用户窗体上的动态按钮,c#,visual-studio-2017,C#,Visual Studio 2017,我正在尝试用C语言建立一个小型桌面应用程序,它可以读取xml文件,并根据文件中的节点生成按钮 XML文件具有以下节点: <?xml version="1.0" encoding="UTF-8"?> <templates> <version>1.0</version> <incident> <template id="1"> <name>some topic</name> <descr

我正在尝试用C语言建立一个小型桌面应用程序,它可以读取xml文件,并根据文件中的节点生成按钮

XML文件具有以下节点:

<?xml version="1.0" encoding="UTF-8"?>
<templates>
<version>1.0</version> 
<incident>
<template id="1">

  <name>some topic</name>
  <description>Use this for something</description>
  <item id="1">field 1</item>
  <item id="2">field 2</item>
  <item id="3">field 3</item>
  <item id="4">fiel 4</item>

</template>
我有一个带有预定义按钮的用户表单Form1,它正在工作,但其中一个按钮应该读取此xml文件并打开一个新的用户表单Form3,表单上有数字分配的按钮

我在buton下有以下代码:

private void button1_Click(object sender, EventArgs e)
    {
        string Username = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();

        var result = Username.Length <= 4 ? "" : Username.Substring(4);

        string path = $"C:\\Users\\{result}\\Documents\\template_manager\\config.xml";
        //MessageBox.Show(path);

        XmlDocument doc = new XmlDocument();
        doc.Load(path);
        XmlTextReader xtr = new XmlTextReader(path);

        string string_title = "";
        while (xtr.Read())
        {
            if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "name")
            {


                // string string_title = xtr.ReadElementString();
                string_title += xtr.ReadElementString() + Environment.NewLine;
               //MessageBox.Show("Title: " + Environment.NewLine + string_title);

                //var Form3 = new Form3(string_title);
                //Form3.show();
                Form3 frm3 = new Form3(string_title);
                {
                    frm3.ShowDialog();
                }
            }
在表格3中,我有以下代码:

string dataFromForm1;
    public Form3(string data)
    {
        //getting Windows Logon ID from the system and assigning it to a string kind variable
        string Username = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
        //-re-assigning windows logon ID to a variable
        //string str = Username;
        //Trimming the logon ID (removing "G0X/")
       string result = Username.Length <= 4 ? "" : Username.Substring(4);
        //passing the path of the xml file to a variable named path

        string path = $"C:\Users\\{result}\\Documents\\e2e_template_manager\\config.xml";
        //MessageBox.Show(path);

        XmlDocument doc = new XmlDocument();
        doc.Load(path);
        XmlNodeList templates = doc.SelectNodes(path);


        int x = 10;
        int y = 10;


        foreach (XmlNode template in templates)
        {
            string name = template.SelectSingleNode("name").InnerText.Trim();
            Button button = new Button
            {
                Text = name,
                Left = x,
                Top = y
            };
            Controls.Add(button);
          y += button.Height + 5;
        }
        InitializeComponent();

    }
    public void show()
    {
        MessageBox.Show("Title: " + dataFromForm1);
    }

}

你能帮我解决这个问题吗?此外,动态生成的按钮应指向表单4或表单5。

正如评论中所述,您没有说明问题是什么,您希望发生的是什么。我猜你的表格3没有出现。它没有出现是因为你没有让它出现

//var Form3 = new Form3(string_title);
//Form3.show();
Form3 frm3 = new Form3(string_title);
{  // BTW: these braces are not necessary
    frm3.ShowDialog();
}
注释掉的版本更接近,除非您希望调用已创建的表单:

var frm3 = new Form3(string_title);
frm3.Show(this);  // ...and give it the parent window
使用调试器检查代码中哪里有问题。有很多事情可能会出错,比如不正确的路径、不正确的文件格式、错误的参数

关于代码的一些要点:

一些变量以大写开头,而另一些变量以小写开头。虽然这对编译器来说并不重要,但它显示出缺乏努力和一致性。编写C代码时,通常应遵循Microsoft约定。即字段、变量和参数为camelCase,方法、属性和类型为PascalCase。 为了提高可读性,您可以使用逐字插入字符串作为路径,请参见。更好的方法是使用System.Environment.GetFolderPath。 错误项:在C中,字符串被创建为空。无需将string_title设置为空字符串。 替代点:在构建字符串时使用StringBuilder。 是否确实要为每个节点名称创建新的Form3? 您的输入文件fiel 4中似乎缺少一个dis 你读过关于干燥原理的书吗?button1\u Click的前3行与Form3构造函数的前3行相同。生成一个函数以获取该路径。这将使代码更易于维护。 在Form3构造函数中,似乎您正在为2个不同目的的文件使用path变量来加载,XML路径到一个节点,但使用相同的变量。几乎可以肯定,您不会找到任何节点! 结果是变量名不好。除了包含当前函数结果的变量外,通常应该避免使用它。 我认为在调用InitializeComponent之前创建控件不是一个好主意。您可能应该先让WinForms创建控件,然后再添加您的控件。 为什么要在事件处理程序和Form3构造函数中加载文档?您可能应该将已经加载的信息传递给构造函数,或者更好地传递给公共函数LoadFromTemplate。 如果string_title实际上是一个标题,那么它不应该包含Environment.NewLine。如果没有,则应使用更好的名称。 在任何情况下,都怀疑它是调用方的标题和新表单的数据。 此外,不应将字符串作为变量名的前缀。匈牙利符号在现代语言和IDE中被认为是过时的。 你应该给你的表单起一个有意义的名字。 如果要将事件处理程序添加到表单中,只需在添加按钮后添加事件处理程序,并在关闭表单时删除事件处理程序即可。 删除对问题不有用的注释掉的代码。 对于像VisualStudio这样具有良好调试器的现代IDE,使用MessageBox跟踪值很少有用。只需在事件处理程序中放置一个断点,然后在步骤中输入代码并检查变量。对于像上面这样的代码,如果您的问题是用MCVE正确编写的,并且是一个实际的精确问题,那么查找调试器的问题所花费的时间应该会更少

顺便说一句,如果问题是加载数据,那么任何与打开表单相关的代码对于这个问题都是无用的。另一方面,如果问题是显示表单或按钮,则问题不需要任何与加载数据相关的代码。如果你真的有两个问题,那么问两个问题,每一个问题只有与一个特定问题相关的代码

我们不做家庭作业。你必须问一个特定的问题,而不是给我们一堆代码,希望其他人会为你编写整个代码

-更正2-

我的字符串初始化错误。所以原始代码在这一点上是正确的


<>最近,我做C++,而且规则非常不同! Windows窗体?或者别的什么?生成的按钮应该指向Form4或Form5-根本不清楚您的意思。您似乎已经这样做了,那么到底是什么问题?第一种形式的代码似乎与此问题无关。你知道你可以重命名表单,给它们起一个有意义的名字吗?你的代码远远不够简单。当y
如果你问一个问题,你应该始终提供MCVE。而且,你并没有真正说出你的问题或提出问题。如果你需要帮助,那就在你的问题上下点功夫。千万不要硬编码到那样的文档路径。始终使用以下函数:System.Environment.GetFolderPathEnvironment.SpecialFolder.MyDocuments;frm3.ShowDialog;将以模式显示表单。他让它看起来不是问题。你在第三点的陈述是错误的!默认情况下,不初始化局部变量。类字段和自动属性初始化为defaultT,其中T是字段的类型。对于像字符串这样的引用类型,这是null而不是空字符串!。你是对的…当我使用C时,我使用StringBuilder,所以我几乎不需要将字符串初始化为空,当我这样做时,我使用的是string.empty。你的更正仍然是错误的。由于string_title是一个局部变量,因此它不会被隐式赋值。您必须显式地将其初始化为所需的值。说明必须在获取局部变量值的每个位置明确地为其赋值。对于局部变量,除catch子句或foreach语句中声明的变量外,如果在使用它之前未为其赋值,则会出现编译器错误CS0165使用未赋值局部变量“string\u title”