I have a small program that generates four dynamic buttons on load in a flowLayoutPanel1 and a static save button.
My aim is to save the dynamic button colors so that when the form is reloaded or opened again the colors of the dynamic buttons are loaded back up in the same state as saved.
Below I will include my code which has been commented to demonstrate what I have attempted.
I am using an xml file to save the button state and included a class that holds the state. However the method I am using works fine if a create my buttons to save statically. (I have only tried it with one static button)
Interface:
class that holds state:
public class MyFormState
{
public string ButtonBackColor { get; set; }
}
Form code:
public partial class Form1 : Form
{
//Form Member
MyFormState state = new MyFormState();
Button btn;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//loading xml file if it exists
if (File.Exists("config.xml"))
{
loadConfig();
}
//Genrating dynamic buttons
// flowLayoutPanel1.Controls.Clear();
for (int i = 0; i <= 3; ++i)
{
btn = new Button();
btn.Text = " Equation " + i;
flowLayoutPanel1.Controls.Add(btn);
//click event of buttons
btn.Click += new EventHandler(btn_Click);
}
btn.BackColor = System.Drawing.ColorTranslator.FromHtml(state.ButtonBackColor);
}
//method to load file
private void loadConfig()
{
XmlSerializer ser = new XmlSerializer(typeof(MyFormState));
using (FileStream fs = File.OpenRead("config.xml"))
{
state = (MyFormState)ser.Deserialize(fs);
}
}
//saving the xml file and the button colors
private void writeConfig()
{
using (StreamWriter sw = new StreamWriter("config.xml"))
{
state.ButtonBackColor = System.Drawing.ColorTranslator.ToHtml(btn.BackColor);
XmlSerializer ser = new XmlSerializer(typeof(MyFormState));
ser.Serialize(sw, state);
}
}
int count = 0;
//backcolor change
void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (count == 0)
{
button.BackColor = Color.Red;
count++;
}
else if (count == 1)
{
button.BackColor = Color.Blue;
count--;
}
}
//save file
private void btnSave_Click(object sender, EventArgs e)
{
writeConfig();
}
}
Any suggestions on what i should change so that it works for me? Thanks
Your code works fine but only for the last button. You have 4 buttons but only have one MyFormState object. When creating the buttons you always use the same private field btn. So you need arrays of 4 MyFormState objects and 4 buttons.
MyFormState[] states = new MyFormState[4];
Button[] buttons = new Button[4];
private void Form1_Load(object sender, EventArgs e)
{
if (File.Exists("config.xml"))
{
loadConfig();
}
for (int i = 0; i < 4; ++i)
{
buttons[i] = new Button();
buttons[i].Text = " Equation " + i;
flowLayoutPanel1.Controls.Add(buttons[i]);
buttons[i].Click += new EventHandler(btn_Click);
if (states[i] != null)
{
buttons[i].BackColor = ColorTranslator.FromHtml(states[i].ButtonBackColor);
}
}
}
private void loadConfig()
{
XmlSerializer ser = new XmlSerializer(typeof(MyFormState[]));
using (FileStream fs = File.OpenRead("config.xml"))
{
states = (MyFormState[])ser.Deserialize(fs);
}
}
private void writeConfig()
{
for (int i = 0; i < 4; i++)
{
if (states[i] == null)
{
states[i] = new MyFormState();
}
states[i].ButtonBackColor = ColorTranslator.ToHtml(buttons[i].BackColor);
}
using (StreamWriter sw = new StreamWriter("config.xml"))
{
XmlSerializer ser = new XmlSerializer(typeof(MyFormState[]));
ser.Serialize(sw, states);
}
}
Related
I have problem with one function. Function "Usun" must delete both line in listbox and the same data from txt file** Can anyone help me?
using System;
namespace BazaKlientow2
{
public partial class Form1 : Form
{
private Klient[] lista = new Klient[1];
public Form1()
{
InitializeComponent();
}
private void Write(Klient obj)
{
StreamWriter sw = new StreamWriter("Klienci.txt");
sw.WriteLine(lista.Length + 1);
sw.WriteLine(obj.Imie);
sw.WriteLine(obj.Nazwisko);
sw.WriteLine(obj.Firma);
sw.WriteLine(obj.NIP);
for(int x = 0; x <lista.Length; x++)
{
sw.WriteLine(lista[x].Imie);
sw.WriteLine(lista[x].Nazwisko);
sw.WriteLine(lista[x].Firma);
sw.WriteLine(lista[x].NIP);
}
sw.Close();
}
private void Read()
{
StreamReader sr = new StreamReader("Klienci.txt");
lista = new Klient[Convert.ToInt32(sr.ReadLine())];
for (int x = 0; x < lista.Length; x++)
{
lista[x] = new Klient();
lista[x].Imie = sr.ReadLine();
lista[x].Nazwisko = sr.ReadLine();
lista[x].Firma = sr.ReadLine();
lista[x].NIP = sr.ReadLine();
}
sr.Close();
}
private void Display()
{
listaKlientow.Items.Clear();
for( int x=0; x < lista.Length; x++)
{
listaKlientow.Items.Add(lista[x].ToString());
}
}
private void ClearForm()
{
txtImie.Text = String.Empty;
txtNazwisko.Text = String.Empty;
txtFirma.Text = String.Empty;
txtNip.Text = String.Empty;
}
private void dodaj_Click(object sender, EventArgs e)
{
Klient obj = new Klient();
obj.Imie = txtImie.Text;
obj.Nazwisko = txtNazwisko.Text;
obj.Firma = txtFirma.Text;
obj.NIP = txtNip.Text;
Write(obj);
Read();
Display();
ClearForm();
}
private void Form1_Load(object sender, EventArgs e)
{
Read();
Display();
}
private void sortuj_Click(object sender, EventArgs e)
{
Sortowanie();
Display();
}
private void Sortowanie()
{
Klient temp;
bool swap;
do
{
swap = false;
for(int x=0;x<lista.Length -1;x++)
{
if(lista[x].Imie.CompareTo(lista[x+1].Nazwisko) >0)
{
temp = lista[x];
lista[x] = lista[x + 1];
lista[x + 1] = temp;
swap = true;
}
}
} while (swap == true);
}
private void usun_Click(object sender, EventArgs e)
{
Usun();
}
private void Usun()
{
**//i cant do this. this function must delete both line in listbox and the same data from txt file**
}
}
}
Function "Usun" must delete both line in listbox and the same data from txt file** Can anyone help me?
You need to read the lines from the file and store then in a List<string> memory. You also need to set the DataSource property of the ListBox to those lines. When you want to remove a line, remove it from the List<string> in memory. Then write the whole list back to the file. Then reset the DataSource property of the ListBox.
Here is an example. In this example, I create a file with "1", "2" and "3" as the lines. Then when the user clicks a button, I remove "1" from the list in memory and write the list to the file. Then I refresh the listbox.
public partial class Form1 : Form {
private List<string> linesInFile;
public Form1() {
InitializeComponent();
File.WriteAllLines( "Lines.txt", new string[] { "1", "2", "3" } );
this.linesInFile = File.ReadAllLines( "Lines.txt" ).ToList();
this.listBox1.DataSource = this.linesInFile;
}
private void Remove_Click(object sender, EventArgs e) {
this.linesInFile.Remove( "1" );
File.WriteAllLines( "Lines.txt", this.linesInFile );
this.listBox1.DataSource = null;
this.listBox1.DataSource = this.linesInFile;
}
}
i was trying to make this code:
public void _open_Click_1(object sender, EventArgs e)
{
_playList.Items.Clear();
_openFile.Multiselect = true;
_openFile.Filter = "Mp3 Files|*.mp3|Avi Files|*.avi|Mp4 Files|*.mp4";
_openFile.ShowDialog();
doc = _openFile.SafeFileNames;
path = _openFile.FileNames;
for (int i = 0; i < doc.Length; i++)
{
_playList.Items.Add(doc[i]);
}
}
from a class
so i created a class called mplayer
and then an instance of the form
and put all that code in there
what suppose to happen is when i click a button
file dialog opens
and all selected song names would go into a listbox
for some reason it doesn't open and no compilation nor exception errors pops
please advise
As I can see the event handler is correctly assigned. Btw try this code, it is working in my project:
public Form1()
{
InitializeComponent();
_open.Click += new EventHandler(_open_Click_1);
}
private void _open_Click_1(object sender, EventArgs e)
{
_openFile = new OpenFileDialog();
_playList.Items.Clear();
_openFile.Multiselect = true;
_openFile.Filter = "Mp3 Files|*.mp3|Avi Files|*.avi|Mp4 Files|*.mp4";
_openFile.ShowDialog();
var doc = _openFile.SafeFileNames;
var path = _openFile.FileNames;
for (int i = 0; i < doc.Length; i++)
{
_playList.Items.Add(doc[i]);
}
}
Note: I was using local variables for the selected file names and path.
maybe i wasn't explaining myself very well. im trying to call a class which does that. like this
public static class mplayer
{
public static void openMusic()
{
PhoenixDownloader.searchForm frm = new searchForm();
frm._playlist.items.clear();
frm._openfile.multiselect = true;
frm._openfile.filter = "mp3 files|*.mp3|avi files|*.avi|mp4 files|*.mp4";
frm._openfile.showdialog();
frm.doc = frm._openfile.safefilenames;
frm.path = frm._openfile.filenames;
for (int i = 0; i < frm.doc.length; i++)
{
frm._playlist.items.add(frm.doc[i]);
}
}
}
}
and on the event part:
public void _open_Click_1(object sender, EventArgs e)
{
mplayer();
}
and it it doesn't happen
I want to add many buttons in random position to the form (C#) but I don't from these buttons overlapping, So the question is Can I know if the point is empty or there are already object in this point?
Try something like this out:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Random R = new Random();
private List<Button> Buttons = new List<Button>();
private void button1_Click(object sender, EventArgs e)
{
while (Buttons.Count > 0)
{
Buttons[0].Dispose();
Buttons.RemoveAt(0);
}
bool overlapping;
for(int i = 1; i <= 10; i++)
{
Button btn = new Button();
btn.Text = i.ToString();
this.Controls.Add(btn);
do
{
overlapping = false;
btn.Location = new Point(R.Next(this.ClientSize.Width - btn.Width), R.Next(this.ClientSize.Height - btn.Height));
foreach(Button otherBtn in Buttons)
{
if (btn.Bounds.IntersectsWith(otherBtn.Bounds))
{
overlapping = true;
break;
}
}
} while (overlapping);
Buttons.Add(btn);
}
}
}
I am creating some picturebox dynamically and click event for picturebox as follows
Image myImage = Image.FromFile("image/Untitled6.png");
PictureBox[] txtTeamNames = new PictureBox[5];
for (int i = 0; i < txtTeamNames.Length; i++)
{
var txt = new PictureBox();
txtTeamNames[i] = txt;
txtTeamNames[i].Image = myImage;
txtTeamNames[i].Height = 53;
txtTeamNames[i].Width = 48;
this.panel1.Controls.Add(txtTeamNames[i]);
txtTeamNames[i].Visible = true;
txtTeamNames[i].Click += new EventHandler(this.clcikeventhandle);
}
When someone clicks on any picture box, how do I find its array index and name?
void clickEventHandler(object sender, EventArgs e)
{
//???
}
You can access the PictureBox via the sender argument. So try this:
PictureBox[] txtTeamNames;
void YourMethod()
{
Image myImage = Image.FromFile("image/Untitled6.png");
txtTeamNames = new PictureBox[5];
//The same as your code
}
void clcikeventhandle(object sender, EventArgs e)
{
int index = txtTeamNames.IndexOf(sender As PictureBox);
}
EDIT: Approach #2
But if you are not happy with declaring that array in the class scope you can try this approach:
//Same as your code
for (int i = 0; i < txtTeamNames.Length; i++)
{
//Save as your code
txtTeamNames[i].Tag = i; // ADD THIS LINE
}
Then:
void clcikeventhandle(object sender, EventArgs e)
{
int index = int.Parse((sender as PictureBox).Tag.ToString());
}
Another suggestion - create a custom class, which inherits from PictureBox. It will have an extra Index property. And you can set it between these two lines:
txtTeamNames[i].Visible = true;
//assign the index here
txtTeamNames[i].Click += new EventHandler(this.clcikeventhandle);
like so:
txtTeamNames[i].Index = i;
Then in the handler:
void clickEventHandle(object sender, EventArgs e)
{
PictureBox pbox = sender As PictureBox;
int index = pbox.Index();
string name = pbox.Name();
}
You keep the same scope of variables, which may be useful if you are concerned about it. If you are okay with upgrading scope of txtTeamNames to class level, see another answer by Hossein Narimani Rad.
namespace your_name_project
{
public partial class Form_Begin : Form
{
PictureBox[] pictureBoxs = new PictureBox[6];
public Form_Begin()
{
InitializeComponent();
pictureBoxs[0] = pictureBox1; pictureBoxs[1] = pictureBox2; pictureBoxs[2] = pictureBox3;
pictureBoxs[3] = pictureBox4; pictureBoxs[4] = pictureBox5; pictureBoxs[5] = pictureBox6;
}
//continue
List<PictureBox> pictureBoxes = new List<PictureBox>();
private void buttonX1_Click(object sender, EventArgs e)
{
for (int i = 0; i <3; i++)
{
pictureBoxs[i].Image =your_name_project.Properties.Resources.image_1;// load image1 and Image_2from resource in property of picturebox
}
for (int i = 3; i < 6; i++)
{
pictureBoxs[i].Image = your_name_project.Properties.Resources.Image_2;
}
}
}
}
I've tried the 1st approach cited above, but it did not work for me. I needed to change the syntax in order to work. I am unsure why, but my way for approach 1 to work would be:
PictureBox[] txtTeamNames;
void YourMethod()
{
Image myImage = Image.FromFile("image/Untitled6.png");
txtTeamNames = new PictureBox[5];
//The same as your code
}
void clcikeventhandle(object sender, EventArgs e)
{
int index = Array.IndexOf(txtTeamNames, sender); //DIFFERENT HERE
}
If anyone has an idea...
I need to make a ListBox that displays how often a Button is clicked.
The user chooses how many buttons are available to click. Here is what I've tried:
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
for (int i = 0; i < freq_array[clicked]; i++)
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
freq_array uses the 'clicked' variable to add to the frequency that button has been clicked. Or, it's supposed to.
When I debug it, 'clicked' always comes out to 0. I want 'clicked' to equal the text value of the button that's clicked. When I try to run the program, I get an error saying "Input string was not in correct format."
Edit:
I was able to fix my program with help from you guys. I realized I didn't show enough of my code to be clear enough, and I apologize for that. I had to add some things and move things around and got it soon enough. Thank you all.
Here is the code just for those who may need help in the future:
public partial class Form1 : Form
{
int[] freq_array = new int[11];
int[] numList = new int[11];
int oBase = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
invisiblity();
}
private void invisiblity()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
ctrl.Visible = false;
}
}
private void btnSetBase_Click(object sender, EventArgs e)
{
Form2 frmDialog = new Form2();
frmDialog.ShowDialog(this);
if (frmDialog.DialogResult == DialogResult.OK)
{
oBase = frmDialog.Base;
//lblOutDigits.Text = oBase.ToString();
for (int i = 0; i < oBase; i++)
{
numList[i] = i;
}
}
ShowBaseButtons(oBase);
}
private void ShowBaseButtons(int last_digit)
{
invisiblity();
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
if (int.Parse(ctrl.Text) <= last_digit - 1)
ctrl.Visible = true;
}
}
private void btnN_Click(object sender, EventArgs e)
{
lblOutDigits.Text += ((Button)(sender)).Text;
int clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
}
private void btnShowFreq_Click(object sender, EventArgs e)
{
lstFrequencies.Items.Clear();
for (int i = 0; i < oBase; i++)
lstFrequencies.Items.Add(numList[i] + " \t\t\t" + freq_array[i]);
}
Your code should work as long as your Button Text is actually just a number. Since what you are trying to do is create an index, what I usually do is use the Tag Property of the control, set it to the Index I want in the designer and then cast that to an Int.
i.e.
if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
freq_array[clicked]++;
I believe what is happening is that you are not initializing your ListBox, This example Code does work using your initial method. Just create a new Form and paste it in and test.
public partial class Form1 : Form
{
ListBox lstFrequencies = new ListBox();
int[] freq_array = new int[10];
public Form1()
{
InitializeComponent();
Size = new Size(400, 400);
lstFrequencies.Location = new Point(150, 0);
lstFrequencies.Size = new Size(150, 200);
Controls.Add(lstFrequencies);
int top = 0;
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Size = new Size(70, 30);
btn.Location = new Point(5, top);
Controls.Add(btn);
top += 35;
btn.Tag = i;
btn.Text = i.ToString();
btn.Click += new EventHandler(btn_Click);
lstFrequencies.Items.Add(i.ToString());
}
}
void btn_Click(object sender, EventArgs e)
{
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked]; //Cleaned up you do not need to iterate your list
// Using my example code
//if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
//{
// freq_array[clicked]++;
// lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
//}
}
}
Your code always comes out to 0 because you never assign last clicked value to button text. Try this code:
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
clicked = Convert.ToInt32(((Button)sender).Text);
lstFrequencies.Items.Add(((Button)sender).Name + " " + ++clicked);
button1.Text = clicked.ToString(); // you lose this line
}
EDIT: Counter from variable member
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
// if you want to display button name, change .Text to .Name
lstFrequencies.Items.Add(((Button)sender).Text + " " + ++clicked);
}