Reputation: 945
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
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
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
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