用户表单上的动态按钮

时间:2019-02-12 22:03:25

标签: 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>
  <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),上面带有动态分配的按钮。

我的按钮下面有这个代码:

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

}

您能帮助我如何解决这个问题吗?并且动态生成的按钮应该指向Form4或Form5。

2 个答案:

答案 0 :(得分:1)

正如评论中提到的那样,您尚未说明问题所在(您希望发生的未发生的事情)。我的猜测是您的Form3没有出现。之所以没有出现,是因为您没有告诉它出现。

//var Form3 = new Form3(string_title);
//Form3.show();
Form3 frm3 = new Form3(string_title);
{  // BTW: these braces are not necessary
    frm3.ShowDialog();
}

已注释掉的版本更接近,除了您想在创建的表单上调用Show

var frm3 = new Form3(string_title);
frm3.Show(this);  // ...and give it the parent window

答案 1 :(得分:1)

使用调试器检查代码中存在问题的地方。许多事情可能会出错,例如路径错误,文件格式错误,参数错误……

关于您的代码的几点:

  • 某些变量以大写字母开头,而其他变量以小写字母开头。尽管对于编译器而言并不重要,但它显示出缺乏工作量和一致性。编写C#代码时,通常应遵循Microsoft约定。即字段,变量和参数是camelCase,方法,属性和类型是PascalCase。
  • 为提高可读性,可以对path使用逐字插入的字符串(请参见https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated)。更好的是,使用System.Environment.GetFolderPathhttps://docs.microsoft.com/en-us/dotnet/api/system.environment.getfolderpath?view=netframework-4.7.2)。
  • 错误的项目:在C#中,字符串创建为空。无需将string_title设置为空字符串。
  • 替代点::构建字符串时使用StringBuilder
  • 您真的要为每个节点Form3创建一个新的name吗?
  • 您的输入文件中似乎缺少d<item id="4">fiel 4</item>
  • 您是否曾经读过 DRY原理https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)? button1_Click的前3行与Form3构造函数的前3行相同。创建一个函数以获取该路径。这将使代码更易于维护。
    • Form3构造函数中,似乎您正在将path变量用于两种不同目的(要加载的文件,到节点的XML路径),但使用的是同一变量。 几乎可以确定您找不到任何节点!
  • result是一个不好的变量名。您通常应该避免使用它,除了会包含当前函数结果的变量。
  • 我认为在调用InitializeComponent之前创建控件不是一个好主意。您可能应该先让WinForms创建控件,然后再添加控件。
  • 为什么要同时在事件处理程序和Form3构造函数中加载文档?您应该将已经加载的信息传递给构造函数,或者最好将其传递给公共函数LoadFromTemplate
  • 如果string_title确实是标题,则它不应包含Environment.NewLine。如果没有,那么应该使用更好的名称。
  • 在任何情况下,它都是调用方的标题和新表单的数据都是可疑的。
  • 此外,您不应包含string_作为变量名的前缀。匈牙利符号主要被现代语言和IDE淘汰。
  • 您应该为表格命名。
  • 如果要向表单添加事件处理程序,只需在添加按钮后添加它(在关闭表单时删除处理程序)即可。
  • 删除注释掉对问题无用的代码。

对于像Visual Studio这样具有良好调试器的现代IDE,使用MessageBox来跟踪值很少有用。只需在事件处理程序中放置一个断点,然后执行代码并检查变量。对于上述代码,应该花费较少的时间来查找调试器的问题,因为调试器花费了您编写问题的时间(或者如果您的问题是正确编写的,则应该花费 > MCVE 和一个实际的精确问题)。

顺便说一句,如果问题是在加载数据,那么与打开表单相关的任何代码对于该问题都是无用的。另一方面,如果问题是显示表单或按钮,则问题不需要任何与加载数据有关的代码。如果您确实有2个问题,则每个问题要问2个问题,仅提供与一个特定问题相关的代码

我们不做作业。您必须提出一个特定的问题,不要给我们提供一堆代码,希望别人能为您编写整个代码。

—修正#2 —

我对字符串初始化是错误的。因此,原始代码在这一点上是正确的。

最近,我在做C ++,规则却大不相同!