I have lots of textboxes on a form that I want to fill in with lines I have saved in a text file. I have the text file be read and save every line into an array. Then I want to set each line equal to a corresponding text box.
I currently have it all saved line by line like this:
string[] lines = System.IO.File.ReadAllLines("savedWorkout.txt");
textBox1_1.Text = lines[0];
textBox1_2.Text = lines[1];
textBox1_3.Text = lines[2];
textBox1_4.Text = lines[3];
textBox1_5.Text = lines[4];
textBox1_6.Text = lines[5];
textBox1_7.Text = lines[6];
textBox2_1.Text = lines[7];
textBox2_2.Text = lines[8];
textBox2_3.Text = lines[9];
textBox2_4.Text = lines[10];
textBox2_5.Text = lines[11];
textBox2_6.Text = lines[12];
textBox2_7.Text = lines[13];
I have tried to use a for(i = 0; i < 7, i++) loop, replacing each number in the text box name with i, but I am unsure on how to do this correctly, if possible. Any help would be appreciated.
The textbox names have two numbers. With i being the index in the lines array, the first one can be calculated with
int n1 = i / 7 + 1;
The second one with
int n2 = i % 7 + 1;
Together
for (int i = 0; i < lines.Length; i++) {
int n1 = i / 7 + 1;
int n2 = i % 7 + 1;
Controls[$"textBox{n1}_{n2}"].Text = lines[i];
}
Consider using a DataGridView instead.
See also: Is it possible to bind an array to DataGridView control?.
The following reads lines from a file, dynamically creates a TextBox for each line on to a panel named panel1 were panel1 AutoScroll is set to true so if there are more lines than real estate a scrollbar will be used.
As presented in the screenshot, the width may need to be adjusted to accommodate the text width for the lines.
Place this class into your project
public class TextBoxOperations
{
public static List<TextBox> List { get; set; }
public static int Top { get; set; }
public static int Left { get; set; }
public static int Width { get; set; }
public static int HeightPadding { get; set; }
public static string BaseName { get; set; }
public static Control ParentControl { get; set; }
private static int _index = 1;
public static void Initialize(Control pControl, int pTop, int pBaseHeightPadding, int pLeft, int pWidth)
{
ParentControl = pControl;
Top = pTop;
HeightPadding = pBaseHeightPadding;
Left = pLeft;
Width = pWidth;
List = new List<TextBox>();
}
private static void Create(string text)
{
var button = new TextBox()
{
Name = $"{BaseName}{_index}",
Text = text,
Width = Width,
Location = new Point(Left, Top),
Parent = ParentControl,
Visible = true,
Tag = _index
};
List.Add(button);
ParentControl.Controls.Add(button);
Top += HeightPadding;
_index += 1;
}
public static void Build(string[] lines)
{
foreach (var line in lines)
{
Create(line);
}
}
public static void Save(string fileName)
{
File.WriteAllLines(fileName, List.Select(tb => tb.Text).ToArray());
}
}
Form code with a panel and two buttons, first button loads lines, second provides a method to save the lines to the same file.
public partial class Form1 : Form
{
private readonly string _fileName = "savedWorkout.txt";
public Form1()
{
InitializeComponent();
panel1.AutoScroll = true;
}
private void RunSampleButton_Click(object sender, EventArgs e)
{
var lines = File.ReadAllLines(_fileName);
TextBoxOperations.BaseName = "LineTextBox";
TextBoxOperations.Initialize(panel1, 20, 30, 10, 400);
TextBoxOperations.Build(lines);
}
private void SaveButton_Click(object sender, EventArgs e)
{
TextBoxOperations.Save(_fileName);
}
}
Related
I have some problem with GridView component. My task is to insert into the gridview data from a class called a book whose number of pages is greater than 100. Class:
public class Knjiga {
public string nazivKnjige { get; set; }
public string imeAutora { get; set; }
public int brStr { get; set; }
public int ID { get; set; }
public Knjiga(string naziv, string ime, int broj, int id) {
nazivKnjige = naziv;
imeAutora = ime;
brStr = broj;
ID = id;
}
}
I try something like this:
List<Knjiga> biblioteka = new List<Knjiga>() {
new Knjiga("Mali Princ", "Hans Kristiansen Andersen", 355, 009),
new Knjiga("Na Drini cuprija", "Ivo Andric", 100, 088),
new Knjiga("Starac i more", "Ernest Hemingvej", 67, 033),
new Knjiga("Covek posle rata", "Dusan Vasiljev", 255, 011),
new Knjiga("Gradinar", "Rabindranat Tagore", 125, 077)
};
protected void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
for (int i = 0; i < biblioteka.Count; i++)
{
if (biblioteka[i].brStr > 100)
{
GridView1.DataSource = biblioteka;
GridView1.DataBind();
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < biblioteka.Count; i++)
{
if (biblioteka[i].brStr > 100)
{
GridView1.DataSource = biblioteka;
GridView1.DataBind();
}
}
}
But when I start a project, all the data is inserted into the gridview, regardless of whether its number of pages exceeds 100. Does anyone know how to insert only those objects where the number of pages is greater than 100 ??
Before binding the data, to grid view, prepare the data source based on your business.
You are binding the same data multiple times, as the data binding logic present in for-loop
Hi I am trying to dynamically create Buttons and TextBoxes from a List in my page load.
The Buttons have a click event attached which add one to the TextBox.
At the same time this happens I want to update the according List item to the new number.
My issue is that I am getting an error:
Index was out of range. Must be non-negative and less than the size of
the collection. Parameter name: index
I don't seem to understand why I am getting the error and thus how I could fix my issue.
Below I prepared a code example that recreates the issue:
public partial class _Default : Page
{
List<ProductRates> ProductRateList = new List<ProductRates>() {
new ProductRates(1,"Test",0),
new ProductRates(2,"Test2",0),
new ProductRates(3,"Test3",0)
};
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < ProductRateList.Count; i++)
{
double testing = ProductRateList[i].ProductOrderAmount;
TextBox textBox = new TextBox();
textBox.Text = "0";
textBox.ID = ProductRateList[i].ProductName + "TextBox";
Button plusButton = new Button();
plusButton.Text = "+";
plusButton.ID = ProductRateList[i].ProductName + "PinusButton";
plusButton.Click += (se, ev) => PlusButton_Click(se, ev, ProductRateList,i, textBox);
System.Web.UI.HtmlControls.HtmlGenericControl createButtonDiv =
new System.Web.UI.HtmlControls.HtmlGenericControl("DIV");
createButtonDiv.ID = ProductRateList[i].ProductName + "createButtonDiv";
createButtonDiv.Attributes.Add("class", "col-md-6");
createButtonDiv.Controls.Add(plusButton);
createButtonDiv.Controls.Add(textBox);
ProductPlaceholderDiv.Controls.Add(createButtonDiv);
}
}
void PlusButton_Click(Object sender, EventArgs e, List<ProductRates> ProductRateList, int i, TextBox textBox)
{
string test = textBox.Text;
ProductRateList[i].ProductOrderAmount = 1 + double.Parse(test);
textBox.Text = (ProductRateList[i].ProductOrderAmount).ToString();
}
public class ProductRates
{
public ProductRates(int prodductId, string productName , double productOrderAmount )
{
ProdductId = prodductId;
ProductName = productName;
ProductOrderAmount = productOrderAmount;
}
//Product
public int ProdductId { get; set; }
public string ProductName { get; set; }
public double ProductOrderAmount { get; set; }
}
}
1) Use below new event handler =>
private void PlusButton_Click1(object sender, EventArgs e)
{
Button btn = (Button)sender;
System.Web.UI.HtmlControls.HtmlGenericControl div =(System.Web.UI.HtmlControls.HtmlGenericControl)btn.Parent;
string ProductName = btn.ID.Substring(0, btn.ID.Length - "PinusButton".Length);
TextBox txt = (TextBox)div.FindControl(ProductName + "TextBox");
txt.Text = (Convert.ToInt32(string.IsNullOrEmpty(txt.Text)? "0":txt.Text) + 1).ToString();
}
2) subscribe as =>
plusButton.Click += PlusButton_Click1;
Upvote if the solution works for you..thanks..enjoy coding
I have solved my problem through help of #RiteshKulkarni answer.
Even though there is probably a better solution for this and if someone knows the answer please let me know.
Then on the click event that #RiteshKulkarni posted I added a loop that checks if the name is the corresponding one and use this to store the value in the list.
If someone knows a better way to achieve this please let me know.
public partial class _Default : Page
{
List<ProductRates> ProductRateList = new List<ProductRates>() {
new ProductRates(1,"Test",0),
new ProductRates(2,"Test2",0),
new ProductRates(3,"Test3",0)
};
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < ProductRateList.Count; i++)
{
double testing = ProductRateList[i].ProductOrderAmount;
TextBox textBox = new TextBox();
textBox.Text = ProductRateList[i].ProductOrderAmount.ToString();
textBox.ID = ProductRateList[i].ProductName + "TextBox";
Button plusButton = new Button();
plusButton.Text = "+";
plusButton.ID = ProductRateList[i].ProductName + "PinusButton";
plusButton.Click += PlusButton_Click1;
System.Web.UI.HtmlControls.HtmlGenericControl createButtonDiv =
new System.Web.UI.HtmlControls.HtmlGenericControl("DIV");
createButtonDiv.ID = ProductRateList[i].ProductName + "createButtonDiv";
createButtonDiv.Attributes.Add("class", "col-md-6");
createButtonDiv.Controls.Add(plusButton);
createButtonDiv.Controls.Add(textBox);
ProductPlaceholderDiv.Controls.Add(createButtonDiv);
}
}
private void PlusButton_Click1(object sender, EventArgs e)
{
Button btn = (Button)sender;
System.Web.UI.HtmlControls.HtmlGenericControl div = (System.Web.UI.HtmlControls.HtmlGenericControl)btn.Parent;
string ProductName = btn.ID.Substring(0, btn.ID.Length - "PinusButton".Length);
TextBox txt = (TextBox)div.FindControl(ProductName + "TextBox");
for (int i = 0; i < ProductRateList.Count; i++)
{
if (ProductRateList[i].TextBoxName == ProductName + "TextBox")
{
ProductRateList[i].ProductOrderAmount = double.Parse(txt.Text) + 1;
txt.Text = ProductRateList[i].ProductOrderAmount.ToString();
}
}
}
public class ProductRates
{
public ProductRates(int prodductId, string productName , double productOrderAmount )
{
ProdductId = prodductId;
ProductName = productName;
ProductOrderAmount = productOrderAmount;
}
//Product
public int ProdductId { get; set; }
public string ProductName { get; set; }
public double ProductOrderAmount { get; set; }
public string TextBoxName { get; set; }
}
}
I have a GUI that I am creating which reads a .csv file into a listbox and I am trying to remove a country that is selected when the application is running using a button. I have tried multiple codes however nothing works I either get a error message "Items collection cannot be modified when the DataSource property is set." or nothing happens. below is what I have at the moment. I am also trying to modify a selected item using textboxes.
namespace Countries
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private IList<tradingDetails> listOfCountries;
public class tradingDetails
{
public string Country { get; set; }
public string GDP { get; set; }
public string Inflation { get; set; }
public string TB { get; set; }
public string HDI { get; set; }
public string TP { get; set; }
public string Display
{
get
{
return string.Format("Country = {0} --- GDP = {1} --- Inflation = {2} --- TB = {3} --- HDI = {4} --- TP = {5}", this.Country, this.GDP, this.Inflation, this.TB, this.HDI, this.TP);
}
}
}
public static string[] headers { get; set; }
public void load_Click(object sender, EventArgs e)
{
this.listOfCountries = new List<tradingDetails>();
this.listBox1.ValueMember = "Countries";
this.listBox1.DisplayMember = "Display";
this.InsertInfo();
this.listBox1.DataSource = this.listOfCountries;
}
public void InsertInfo()
{
OpenFileDialog browse = new OpenFileDialog();
browse.Multiselect = true;
if (browse.ShowDialog() == DialogResult.OK)
{
string selectedFile = browse.FileName;
const int MAX_SIZE = 5000;
string[] AllLines = new string[MAX_SIZE];
AllLines = File.ReadAllLines(selectedFile);
foreach (string line in AllLines)
{
if (line.StartsWith("Country"))
{
headers = line.Split(',');
}
else
{
string[] columns = line.Split(',');
tradingDetails fileCountry = new tradingDetails
{
Country = columns[0],
GDP = columns[1],
Inflation = columns[2],
TB = columns[3],
HDI = columns[4],
TP = columns[5]
};
this.listOfCountries.Add(fileCountry);
}
}
}
}
private void DataBind()
{
listBox1.BeginUpdate();
listBox1.DataSource = listOfCountries;
listBox1.EndUpdate();
}
private void remove_Click(object sender, EventArgs e)
{
for (int x = listBox1.SelectedIndices.Count - 1; x >= 0; x--)
{
int idx = listBox1.SelectedIndices[x];
listBox1.Items.RemoveAt(idx);
}
}
private void search_Click(object sender, EventArgs e)
{
listBox1.SelectedItems.Clear();
for (int i = 0; i < listBox1.Items.Count; i++)
{
if (listBox1.Items[i].ToString().Contains(textBox1.Text))
{
listBox1.SetSelected(i, true);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
textBox2.Text = listBox1.Items.Count.ToString();
}
}
}
UPDATE
I have tried this however this deletes all the information in the combo box and not an individual item.
private void remove_Click(object sender, EventArgs e)
{
comboBox1.DataSource = null;
comboBox1.Items.Remove(comboBox1.SelectedValue);
comboBox1.DataSource = listOfCountries;
}
You can't remove items from listbox while it's bounded with a source. For a better understanding, you are trying to remove the item, that your listbox is not an owner of, but the source is(that you have set the datasource of listbox).
Instead, you need to remove the item from the datasource itself.
private void remove_Click(object sender, EventArgs e)
{
for (int x = listBox1.SelectedIndices.Count - 1; x >= 0; x--)
{
int idx = listBox1.SelectedIndices[x];
//listBox1.Items.RemoveAt(idx);
listOfCountries.RemoveAt(idx)l
}
listBox1.RefreshItems();
}
Also, as you are trying to clear all the items from your listbox, this not a good approach to iterate every items and remove all. Instead, you should either clear your listOfCountries or set the listbox1datasource as null.
I am trying to make a game where an image appears, and if it is not clicked the image should disappear. I need help giving my array a value of three, then subtract it in another method.
Code:
NameCount = -1;
NameCount++;
Grid.SetColumn(mole, ranCol);
Grid.SetRow(mole, ranRow);
grid_Main.Children.Add(mole);
for (int i = 0; i < NumofImages; i++)
{
//Where I must give a value to the array of the array to 3 for every image that appears.
}
//Where I am trying to make the image disappear after 3 seconds.
private void deleteMole()
{
NumofImages = TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
NumberofImages = Convert.ToInt32(NumofImages);
for (int j = 0; j < NumofImages; j++)
{
CounterArray[j]--;
if (CounterArray[j] == 0)
{
//Not Sure How to delete image
Thanks for the help!
You could keep track of the images in another array.
After you add the image to the view you should also add it to the array:
images[j] = mole;
Then later:
if (CounterArray[j] == 0)
{
grid_Main.Children.Remove(images[j]);
}
But using static arrays and separating data is not a good idea.
If you can you should better aggregate all the metadata and the image together in the same structure:
class Mole
{
public int Counter { get; set; }
public Control Image { get; set; }
}
and manage them in a single List<Mole>; adding and removing them will be simpler.
Here is some code that illustrates the idea (won't compile):
class Mole
{
public int X { get; set; }
public int Y { get; set; }
public int Counter { get; set; }
public Control Image { get; set; }
public bool IsNew { get; set; }
}
class Test
{
IList<Mole> moles = new List<Mole>();
private static void AddSomeMoles()
{
moles.Add(new Mole{ X = rand.Next(100), Y = rand.Next(100), Counter = 3, Image = new PictureBox(), IsNew = true });
}
private static void DisplayMoles()
{
foreach (Mole mole in moles)
{
if (mole.IsNew)
{
grid_Main.Children.Add(mole.Image);
mole.IsNew = false;
}
}
}
private static void CleanupMoles()
{
foreach (Mole mole in moles)
{
mole.Counter -= 1;
if (mole.Counter <= 0)
{
grid_Main.Children.Remove(mole.Image);
moles.Remove(mole);
}
}
}
static void Main()
{
while (true)
{
AddSomeMoles();
DisplayMoles();
Thread.Sleep(1000);
CleanupMoles();
}
}
}
If you want to give every element in a List a certain value, use a foreach loop. In this case, it would look like:
foreach(int currentElement in CounterArray)
{
currentElement = 3;
}
This will loop through each element of the List and set it to 3.
EDIT: If you're using an array, which you are, you would do the following:
for (int i = 0; i < CounterArray.Length; i++)
{
CounterArray[i] = 3;
}
I am creating a menu with big buttons containing an image, and text. When selected a border is around the button.
The button text is not always the same, and the result of the button click neither.
I have the image name, and text per button set in a struct like this: (there are four of them, but i'll show 2)
struct ConfigDevSubmenu
{
public const string SubMenuBtnText1 = "";
public const string SubMenuBtnText2 = "text submenu 3 button 1";
public const string SubMenuBtnText3 = "text submenu 3 button 2";
public const string SubMenuBtnText4 = "";
public const string SubMenuBtnImg1 = null;
public const string SubMenuBtnImg2 = "Settings.png";
public const string SubMenuBtnImg3 = "LoadFirmware.png";
public const string SubMenuBtnImg4 = null;
public const string SubMenuBtnBorder1 = "Borderstyle.None";
public const string SubMenuBtnBorder2 = "Borderstyle.FixedSingle";
public const string SubMenuBtnBorder3 = "Borderstyle.FixedSingle";
public const string SubMenuBtnBorder4 = "Borderstyle.None";
}
struct AdvancedSubmenu
{
public const string SubMenuBtnText1 = "text submenu 4 button 1";
public const string SubMenuBtnText2 = "text submenu 4 button 2";
public const string SubMenuBtnText3 = "text submenu 4 button 3";
public const string SubMenuBtnText4 = "text submenu 4 button 4";
public const string SubMenuBtnImg1 = "GenerateEncKey.png";
public const string SubMenuBtnImg2 = "Monitoring.png";
public const string SubMenuBtnImg3 = "AdvancedSettings.png";
public const string SubMenuBtnImg4 = "GenerateConfigFile.png";
public const string SubMenuBtnBorder1 = "Borderstyle.FixedSingle";
public const string SubMenuBtnBorder2 = "Borderstyle.FixedSingle";
public const string SubMenuBtnBorder3 = "Borderstyle.FixedSingle";
public const string SubMenuBtnBorder4 = "Borderstyle.FixedSingle";
}
I do not think this can be done much easier without using database files.
To create the buttons I have this function which has as argument the which struct it should use, and in a switch case structure each button is created.
But I've found myself copy-pasting alot in these functions so this must be possible easier. Therefore I tried something like below, but that does not work. I'd like to know whether it is possible to make that work, and how I should do that.
private void createButtons(string Struct)
{
for (int i = 1; i < 5; i++)
{
SubBtnText[i].Text = Struct.SubMenuBtnText[i];
pictureBoxSubBtn[i].Image = Image.FromFile(Struct.SubMenuBtnImg[i]);
panelSubBtn[i].BorderStyle = Struct.SubMenuBtnBorder[i];
}
}
Any suggetions?
Create a class to hold the button text, image name and border styles - say ButtonData.
Create several lists (or arrays) of ButtonData, one per menu.
You can then iterate over the lists and extract the data.
public class ButtonData
{
public ButtonData(string text, string image, BorderStyle border)
{
Text = text;
Image = image;
Border = border;
}
public string Text { get; private set; }
public string Image { get; private set; }
public BorderStyle Border { get; private set; }
}
var devMenuData = new List<ButtonData> {
new ButtonData("", null, "Borderstyle.None"),
new ButtonData("text submenu 3 button 1",
"Settings.png",
Borderstyle.FixedSingle),
...
};
Your function would something like:
private void CreateButtons(IEnumerable<ButtonData> data)
{
foreach (var buttonData in data)
{
SubBtnText[i].Text = buttonData.Text;
pictureBoxSubBtn[i].Image = Image.FromFile(buttonData.Image);
panelSubBtn[i].BorderStyle = buttonData.Border;
}
}
The above amended function will not work as such, as .NET doesn't have control arrays. You could create another list/array to iterate over or index through for this to work.
reflection
class ButtonParameters
{
public string SubMenuBtnText = string.Empty;
public string SubMenuBtnImg = string.Empty;
public string SubMenuBtnBorder = string.Empty;
}
public Dictionary<int, ButtonParameters> CreateParameters(Type type)
{
FieldInfo[] fieldInfos = type.GetFields(
BindingFlags.Public | BindingFlags.Static);
Dictionary<int, ButtonParameters> parameters = new Dictionary<int, ButtonParameters>();
foreach (FieldInfo fieldInfo in fieldInfos)
{
if (fieldInfo.Name.Contains("SubMenuBtnText"))
{
int index = Convert.ToInt32(fieldInfo.Name.Substring(14));
if (!parameters.ContainsKey(index))
{
parameters.Add(index, new ButtonParameters());
}
parameters[index].SubMenuBtnText = (string)fieldInfo.GetValue(null);
}
else if (fieldInfo.Name.Contains("SubMenuBtnImg"))
{
int index = Convert.ToInt32(fieldInfo.Name.Substring(13));
if (!parameters.ContainsKey(index))
{
parameters.Add(index, new ButtonParameters());
}
parameters[index].SubMenuBtnImg= (string)fieldInfo.GetValue(null);
}
else if (fieldInfo.Name.Contains("SubMenuBtnBorder"))
{
int index = Convert.ToInt32(fieldInfo.Name.Substring(16));
if (!parameters.ContainsKey(index))
{
parameters.Add(index, new ButtonParameters());
}
parameters[index].SubMenuBtnBorder= (string)fieldInfo.GetValue(null);
}
}
return parameters;
}
private void createButtons()
{
Dictionary<int, ButtonParameters> buttons = CreateParameters(typeof(AdvancedSubmenu));
for (int i = 1; i < 5; i++)
{
SubBtnText[i].Text = buttons[i].SubMenuBtnText;
pictureBoxSubBtn[i].Image = Image.FromFile(buttons[i].SubMenuBtnImg);
panelSubBtn[i].BorderStyle = buttons[i].SubMenuBtnBorder;
}
}