Creating a leaderboard using TableLayoutPanel - c#

Visual C#. Looking for a way to iterate through the labels of a TableLayoutPanel to show username and score. The list is sorted by score in descending order.
label1.Text = SortedList[0].Username; label2.Text = Convert.ToString(SortedList[0].Score);
label3.Text = SortedList[1].Username; label4.Text = Convert.ToString(SortedList[1].Score);
label5.Text = SortedList[2].Username; label6.Text = Convert.ToString(SortedList[2].Score);
//Continues until I have 10 rows.
I have written it like this to show that each line is a row. I hope that makes what I am trying to achieve here more clear.

I would do something like this: (sorry it has been awhile since I have done WinForms)
var userNameLabels = Label[10]{label1, label3, label5,....}
var userScocreLabels = Label[10]{label2, label4, label6,....}
for(int i = 0; i <= SortedList.Count(); i++){
userNameLabels[i].Text = SortedList[i].Username;
userScocreLabels[i].Text = SortedList[i].Score.ToString();
}

I think right tool for this job is DataGridView
//below property is true by default - will generate columns for properties automatically
yourDataGridView.AutoGenerateColumns = true;
yourDataGridView.DataSource = SortedList;

Related

Read mutliple data from table and create textboxes in form

My table in MySQL is like this:
I have a panel in my Form, and I want to create a TextBox for each data on this table and write sikicerik data to that TextBox's text.
Actually I did it but it creates only one TextBox and selects only the first data on the table.
My code is like this:
int count = oku.FieldCount;
reader.Read();
{
for (int i = 0; i < count; i++)
{
TextBox txt1 = new TextBox();
Point txtyer = new Point(x, y);
txt1.Text = reader["sikicerik"].ToString();
txt1.Name = i.ToString();
x = x + 25;
y = y + 25;
panel1.Controls.Add(txt1);
}
}
It creates just one TextBox and writes "5" in it.
How can I do that repeatedly?
What you need to understand is that you need to call reader.Read() after going through each record. Let's say your result data set has 5 records, so in order to read the 1st record, you need to call reader.Read() which would populate the reader object with the appropriate data. In order to read the 2nd record, you need to again call reader.Read(). Something like this:
int count = reader.FieldCount;
for (int i = 0; i < count; i++)
{
reader.Read();
TextBox txt1 = new TextBox();
Point txtyer = new Point(x, y);
txt1.Location = txtyer;
txt1.Text = reader["sikicerik"].ToString();
txt1.Name = i.ToString();
y = y + 25;
panel1.Controls.Add(txt1);
}
The reason why you may not be able to view all TextBoxes is that you are updating both x and y coordinates of the TextBox. What you may probably want to do is just increment the y coordinate as above and all the TextBoxes would appear vertically. You may also want to resize your form so that the TextBoxes don't get hidden.
Also, as #Steve mentioned in the comments above (which I missed), you need to assign the location of the new TextBoxes created as is done in the code above.
I suppose that you get the FieldCount from the reader variable.
Now in this context you should loop over the read and inside the loop create the textbox for each field retrieved by the original query.
Finally, if you don't set the Location property of the TextBoxes they will be created each on top of the others and you see only the topmost one with the latest value obtained in the loop
// Get the number of fields present in the reader....
int count = reader.FieldCount;
// Read one record at time
while(reader.Read())
{
// Create a textbox for each field in the record
for (int i = 0; i < count; i++)
{
TextBox txt1 = new TextBox();
// Set its location on screen
// Probably if you have many fields you need to
// use a better algorithm to calculate x,y position
txt1.Location = new Point(x, y);
txt1.Text = reader[i].ToString();
txt1.Name = i.ToString();
x = x + 25;
y = y + 25;
panel1.Controls.Add(txt1);
}
}
If you want to create textboxes only for the field sikicerik you have two options. The first one is the recommended because it causes less overhead on your database consist in changing the SELECT query used to build the read to
SELECT sikicerik FROM yourTableName
The other option is a simple change to your code. You don't need to loop over FieldCount because you already know that you are interested in only one field
// Read one record at time
while(oku.Read())
{
textBox1.Text = oku["soru"].ToString();
label1.Text = Form2.sinavno;
// Create the single textbox required for the only field required
TextBox txt1 = new TextBox();
// Set its location on screen
txt1.Location = new Point(x, y);
txt1.Text = oku["sikicerik"].ToString();
txt1.Name = i.ToString();
x = x + 25;
y = y + 25;
panel1.Controls.Add(txt1);
// Repeat the loop for each record.
}

Set the header to be automatically moved to the right in listView?

This is how it looks like when running the program:
This is how it looks like when i manually drag the header to the right:
How can i do it by code to get the second result the manually ?
listView1.Scrollable = true;
listView1.View = View.Details;
ColumnHeader header = new ColumnHeader();
header.Text = "";
header.Name = "col1";
listView1.Columns.Add(header);
string[] lines = File.ReadAllLines(#"c:\temp\countriesandcodes.txt");
for (int i = 1; i < lines.Count(); i += 2)
{
listView1.Items.Add(lines[i]);
}
It looks like your column width is not wide enough to capture the entire text. The method: ListView.AutoResizeColumn is made to do exactly this.
listView1.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent);

How to write to a dynamical number of Textboxes?

I have a form (Windows Forms) with dynamically created textboxes:
TextBox[] tbxCantServ = new TextBox[1];
int i;
for (i = 0; i < tbxCantServ.Length; i++)
{
tbxCantServ[i] = new TextBox();
}
foreach (TextBox tbxActualCant in tbxCantServ)
{
tbxActualCant.Location = new Point(iHorizontal, iVertical);
tbxActualCant.Name = "tbx" + counter++;
tbxActualCant.Visible = true;
tbxActualCant.Width = 44;
tbxActualCant.MaxLength = 4;
this.Controls.Add(tbxActualCant);
}
Now I want to fill them with data, how could I do that?
If I created some textboxes dynamically with the names:
"tbxActualServ.Name = "txt" + counter;"
How can I write in them? How can I access to them?
For example, if I have created tbx1, tbx2 and tbx3, I would have a "for" that fills tbx1.Text with "1", tbx2.Text with "2", and tbx3.Text with "3".
something like
"for from i=0 to counter {
tbx[i] = i
}"
of like:
this.Controls.OfType<TextBox>().Where(r => r.Name == "tbx" + counter).¿¿Write??(r => r.Text = i).ToString();
Thanks!
You could do something like this:
this.Controls.OfType<TextBox>().ToList<TextBox>().ForEach(tb => tb.Text = "bla bla");
Evening,
Guessing from your tags that this is a web forms project.. Im going to have to make some other assumptions.
I am guessing that you are creating your text boxes in code, something like
TextBox tb1 = new TextBox();
form1.Controls.Add(tb1);
TextBox tb2 = new TextBox();
form1.Controls.Add(tb2);
If this is the case then I believe that you could do something like this:
for (int i = 0; i < 2; i++)
{
TextBox tb1 = page.findControl("tb" + i.ToString());
tb1.Text = "This is number " + i.ToString();
}
There is another alternative, you could keep a collection of the controls as you create them, you could then iterate over the collection.
To be honest, without more details about your code it will be difficult to give a full answer, I think that this answers what you are looking for, if not update your question with more details and more of the code (the code where you are dynamically creating the controls would be useful)
While it's possible to access controls by their names (the way you do it depends on the technology - are you using WinForms, WPF, Web Forms, ...?), using an array of controls is a much better solution. Here's some pseudo-C#:
MyControl[] controls = new MyControl[length];
for(int n = 0; n < controls.Length; n++)
{
controls[n] = new MyControl(...);
}
// ...
for(int n = 0; n < controls.Length; n++)
{
DoSomethingWith( controls[n] );
}

Populate text boxes from List Values

I have a list that is created from a LINQ to XML query. The list can contain 1, 2, 3 or 4 values. I have four text boxes on the form that should be populated based on the values in the List, but I can't figure out how to do this because the number of elements in the list will vary. Would it be better to dynamically create the textboxes based on the number of values in the list? How could I go about this?
It seems like this would be a fairly common task, but I have not been able to find a solution. Any help would be greatly appreciated.
Creating dynamically, or just populating an existing 4, it doesn't matter. Choose which one is best for your UI requirements. (maybe even a DGV as has been suggested already)
First you need something to contain the controls, lets say you have a panel called MyPanel which will hold only these textboxes and nothing else...
Here's the load dynamically approach:
MyPanel.Controls.Clear();
int count = 1;
foreach(var item in listOfValues)
{
TextBox tb = new TextBox();
tb.Name = "MyTextbox" + i;
tb.Text = item.ToString();//or whatever property you have for the value
tb.Location = new Point(0, 0 + (25 * (i - 1)));
MyPanel.Controls.Add(tb);
}
Here is the fill existing approach, assuming you have 4 TextBoxes called "TextBox1" for example:
int count = 1;
foreach(var item in listOfValues)
{
TextBox tb = MyPanel.Controls.Find("TextBox" + i) as TextBox;
tb.Text = item.ToString();//or whatever property you have for the value
}
NOTE: You need to be sure that listOfItems does not contain more items than you have textboxes for, otherwise you will get an exception
lets say you have a List
List<int> testList = new List<int>(){1,2,3};
foreach(int i in testList)
{
TextBox test = new TextBox();
test1.Name = "textBox"+i;
youcOntrl.Controls.Add(test1);
}
You can also give them their location and size etc.
Sounds like you want to create a foreach loop and iterate round the linq query creating a new text box on each one and adding it to your form. It'd help to see what you've got so far. I've put an example below using a list instead of a linq query but what comes after it is the same
private void Form1_Load(object sender, EventArgs e)
{
var newList= new List<string> {"box1", "box2", "box3"};
foreach (var boxName in newList)
{
TextBox newTextBox = new TextBox();
newTextBox.Text = boxName;
this.Controls.Add(newTextBox);
}
}
You can create 4 text boxes in the forms designer and set their Visible property to be false as default (from the properties pane).
Then, you can switch on the count property of your list as follows:
switch (els.Count)
{
case 1:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
break;
case 2:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
textBox2.Text = els[2].Value;
textBox2.Visible = true;
break;
case 3:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
textBox2.Text = els[2].Value;
textBox2.Visible = true;
textBox3.Text = els[3].Value;
textBox3.Visible = true;
break;
case 4:
textBox1.Text = els[1].Value;
textBox1.Visible = true;
textBox2.Text = els[2].Value;
textBox2.Visible = true;
textBox3.Text = els[3].Value;
textBox3.Visible = true;
textBox4.Text = els[4].Value;
textBox4.Visible = true;
break;
default:
break;
}
If your list is IEnumerable, then you must first call the ToList() method on it to get a List<XElement> as IEnumerable type does not have a Count property.
If it is four or less then you don't have to create dynamically the textboxes. You could probably disable the textbox(es) that could not be populated. And specially if you name your textbox sequentially like TextBox1, TextBox2 etc then you could probably code like:
for (int i = 1; i <= 4; i++)
{
if (i <= list.Count)
{
this.Controls["TextBox"+i.ToString()].Text = list[i-1];
this.Controls["TextBox"+i.ToString()].Enabled = True;
}
else
{
this.Controls["TextBox"+i.ToString()].Enabled = False;
}
}
So, if you have 2 Items in your List for example then List.Count is 2 and therefore Textbox1 and 2 would be populated and TextBox3 and 4 will be disabled.

Dynamically creating variables in C#

I am trying to do something like this:
for (int i = 1; i < nCounter ; i++)
{
string dvName = "dv" + i.ToString();
System.Windows.Forms.DataGridView dvName = new DataGridView();
// other operations will go here..
}
As you can guess, what I am trying to do is at i == 1, create a DataGridView with name dv1, and at i == 2, create a DataGridView with name dv2, but I can't.
Visual studio squiggles saying "a local variable named dvName is already delared in this scope" I also tried the following:
for (int i = 1; i <nCounter ; i++)
{
System.Windows.Forms.DataGridView dv & i = new DataGridView();
// other operations will go here..
}
But VS squiggles again, I hope you understood what I am trying to accomplish. Can anyone suggest how can I do this?
What you really need is a Dictionary<int, DataGridView> grids. Populate it in your for loop (grids[i] = new DataGridView();) and then, later, use the required grid (grids[someCalculatedIndex])
Hope this helps.
try a data structure where you can hold your variables eg dict etc
System.Collections.Generic.Dictionary<string,System.Windows.Forms.DataGridView>
grids = new Dictionary<string,System.Windows.Forms.DataGridView>();
for (int i = 1; i <nCounter ; i++)
{
grids.Add("dv" + i.ToString(), new DataGridView());
}
// to work on grid 1
DataGridView grid1 = grids["dv1"];
// so on
So your are trying to create the variable name dynamically? That's not possible. Why not use an Array or a List (or even a Dictionary)? Or do you want to just set the name of the control?
var list = new List<DataGridView>();
for (int i = 1; i <nCounter ; i++)
{
System.Windows.Forms.DataGridView dvName = new DataGridView();
dvName.Name = "dv" + i.ToString();
list.Add(dvName);
// other operations will go here..
}
foreach (var dv in list)
{
...do something...
}
DataGridView secondDv = list.Single(dv=>dv.Name == "dv2");
secondDv.DoSomething()
Not clear want you want to do...

Categories

Resources