Kate
Kate

Reputation: 945

How can I save button which was dynamically created

The following code dynamically creates a button at run time in windows forms c#. but after closing / opening the program the button disappears (not saved). I think button properties is saved in the Designer.cs (if I am correct) but I do not know how to save it there. Anyone knows how can I save this button which has been dynamically created? Thank you

 private void button1_Click(object sender, EventArgs e)
    {
        // Create a Button object 
        Button dynamicButton = new Button();

        // Set Button properties
        dynamicButton.Height = 40;
        dynamicButton.Width = 300;
        dynamicButton.BackColor = Color.Red;
        dynamicButton.ForeColor = Color.Blue;
        dynamicButton.Location = new Point(20, 150);
        dynamicButton.Text = "I am Dynamic Button";
        dynamicButton.Name = "DynamicButton";
        dynamicButton.Font = new Font("Georgia", 16);


        dynamicButton.Click += new EventHandler(DynamicButton_Click);


        Controls.Add(dynamicButton);

    }

Upvotes: 1

Views: 757

Answers (3)

Naburi
Naburi

Reputation: 31

Very dirty and quick approach, but it works:

    string serializedButtonsPath = Path.GetDirectoryName(Application.ExecutablePath) + "\\DynamicButtons.csv";
    private void button1_Click(object sender, EventArgs e)
    {
        // Create a Button object 
        Button dynamicButton = new Button();

        // Set Button properties
        dynamicButton.Height = 40;
        dynamicButton.Width = 300;
        dynamicButton.BackColor = Color.Red;
        dynamicButton.ForeColor = Color.Blue;
        dynamicButton.Location = new Point(20, 150);
        dynamicButton.Text = "I am Dynamic Button";
        dynamicButton.Name = "DynamicButton";
        dynamicButton.Font = new Font("Georgia", 16);

        //Naburi: Store function pointer before adding it to the event
        Action<object,EventArgs> dynamicButtonOnClick = dynamicButton_Click;

        dynamicButton.Click += new EventHandler(dynamicButtonOnClick);

        Controls.Add(dynamicButton);

        //Naburi: Serialize button (in strings)
        var membersData = new List<string>();
        membersData.Add(dynamicButton.Height.ToString());
        membersData.Add(dynamicButton.Width.ToString());
        membersData.Add(dynamicButton.BackColor.Name.ToString());
        membersData.Add(dynamicButton.ForeColor.Name.ToString());
        membersData.Add(dynamicButton.Location.X.ToString());
        membersData.Add(dynamicButton.Location.Y.ToString());
        membersData.Add(dynamicButton.Text);
        membersData.Add(dynamicButton.Name);
        membersData.Add(dynamicButton.Font.OriginalFontName);
        membersData.Add(dynamicButton.Font.Size.ToString());
        membersData.Add(dynamicButtonOnClick.Method.Name);

        //Naburi: Store data to csv TODO: improve format!!
        File.AppendAllText(serializedButtonsPath, string.Join(";", membersData) + Environment.NewLine);
    }
    private void button2_Click(object sender, EventArgs e)
    {//Naburi: load buttons
        var serializedButtons = File.ReadAllLines(serializedButtonsPath);
        foreach (var button in serializedButtons)
        {
            var membersData=button.Split(';');

            // Create a Button object 
            Button dynamicButton = new Button();

            // Set Button properties
            var i=0;
            dynamicButton.Height = int.Parse(membersData[i++]);
            dynamicButton.Width = int.Parse(membersData[i++]);
            dynamicButton.BackColor = Color.FromName(membersData[i++]);
            dynamicButton.ForeColor = Color.FromName(membersData[i++]);
            dynamicButton.Location = new Point(int.Parse(membersData[i++]), int.Parse(membersData[i++]));
            dynamicButton.Text = membersData[i++];
            dynamicButton.Name = membersData[i++];
            dynamicButton.Font = new Font(membersData[i++], float.Parse(membersData[i++]));

            //Store method name to make it independent of the index (i)
            var eventMethodName = membersData[i++];

            //Set the event by method name using reflection, the binding flags allow to access the private method
            dynamicButton.Click += (_sender, _e) => 
                    GetType().GetMethod(eventMethodName, BindingFlags.NonPublic|BindingFlags.Instance).Invoke(this, new[] { _sender, _e }
                );

            Controls.Add(dynamicButton);
        }
    }

using System.Reflection, System.Text and System.Collections.Generic

If you have the time, you could make this much nicer storing in a more flexible format like XML maybe creating a .net serializer: https://msdn.microsoft.com/en-us/library/ms171834.aspx

Upvotes: 2

Ian
Ian

Reputation: 30813

If you create the Buttons dynamically, it cannot be saved in the designer.

One way around would be:

When you created that Button, you also store the information which you need to recreate the Button in your custom file (say XMLs). The information may include the name of the button, its size, position, text, fore color, back color etc which you need to recreate the Button.

Then, on Form load. If you find entry in your custom file, you recreate the Button using its info. If you do not find the entry of the Button, then you do not create that on form.

But whenever you create the Button dynamically you create an entry in your custom file and whenever you delete it, you delete its entry.

If you wish, you could also replace the custom file with a database table.

Upvotes: 1

DotNet Fan
DotNet Fan

Reputation: 383

If you create a control dynamically, it cannot be saved to Designer.cs. There are saved just those controls, which you create in Designer or HTML part.

If you need to save a dynamically created control, you can store its parameters to a DB or some custom file, read them from there, create a new control dynamically in C# code and apply those parameters to the control.

Upvotes: 1

Related Questions