Adding a linked label for a list of features - c#

I have a class that contains a list of features and I would like to add a link label for each item in that list. When doing this, I am not able to display all of the features, only the first feature. The smallest code snippet I have is:
foreach (var element in agol.orgServices.services)
{
var linkLabel = new LinkLabel();
linkLabel.Text = element.name + "\n";
linkLabel.Links.Add(new LinkLabel.Link(i, element.url.Length, element.url));
i = linkLabel.Text.Length;
ServicesTab.Controls.Add(linkLabel);
linkLabel.LinkClicked += (s, z) =>
{
System.Diagnostics.Process.Start(z.Link.LinkData.ToString());
};
}
The results I get are:
What I expect to get is something similar to this:
The second image is not individual labels added but a long text string instead. See code snippet below.
finalstring += element.name + "\n"
What am I doing wrong?

I solved it. The link labels were stacking on top of each other so I had to include an increment:
int i=0;
int yi = 30;
int y = 7;
int x = 2;
foreach (var element in agol.orgServices.services)
{
var linkLabel = new LinkLabel();
linkLabel.Name = element.name;
linkLabel.Text = element.name + "\n";
linkLabel.Location = new Point(x, y);
linkLabel.AutoSize = true;
linkLabel.Links.Add(new LinkLabel.Link(i, element.name.Length, element.url));
ServicesTab.Controls.Add(linkLabel);
linkLabel.LinkClicked += (s, z) =>
{
System.Diagnostics.Process.Start(z.Link.LinkData.ToString());
};
y += yi;
//finalServiceList += element.name + "\n";
}

Related

RichTextBox assigning new lines but only last line showing

I'm doing on a GUI to extract position X and Y from GCode by using Regex and print it on richTextBox.
private void button1_Click(object sender, EventArgs e)
{
TextReader read = new System.IO.StringReader(richTextBox1.Text);
int rows = richTextBox1.Lines.Length;
Console.WriteLine(rows);
string[] text = new string[rows];
for (int r = 0; r < rows; r++)
{
text[r] = read.ReadLine();
if (text[r] != null)
{
Match posX = Regex.Match(text[r], #"X([0-9\.]+)");
Match posY = Regex.Match(text[r], #"Y([0-9\.]+)");
GroupCollection posXGroup = posX.Groups;
GroupCollection posYGroup = posY.Groups;
Console.WriteLine(posXGroup[1] + "\t" + posYGroup[1] + "\n");
richTextBox2.Text = (posXGroup[1] + "\t" + posYGroup[1] + "\n");
}
}
}
My GCode:
N65 G2 X21.5091 Y15.5209 Z0.0000 I0.0277 J-0.7392
N120 G2 X21.5280 Y18.0069 Z0.0000 I0.0255 J-0.7476
N210 G2 X21.5968 Y15.0534 Z0.0000 I-0.0483 J-1.2184
N230 G2 X21.6745 Y17.4894 Z0.0000 I0.0473 J-1.2560
My problem is printing the result to richTextBox. It prints only the value of last line: 21.6745 17.4894 but not positions in 3 lines above it. While the console prints successfully. Can someone help me with this?
Quick fix is to concatenate the text:
richTextBox2.Text += (posXGroup[1] + "\t" + posYGroup[1] + "\n");
A better solution is never to use String Concatenation as that will put pressure on the GC as each concatenate adds to the Heap. Instead use a StringBuilder:
private void button1_Click(object sender, EventArgs e)
{
TextReader read = new System.IO.StringReader(richTextBox1.Text);
int rows = richTextBox1.Lines.Length;
Console.WriteLine(rows);
string[] text = new string[rows];
var sb = new StringBuilder();
for (int r = 0; r < rows; r++)
{
text[r] = read.ReadLine();
if (text[r] != null)
{
Match posX = Regex.Match(text[r], #"X([0-9\.]+)");
Match posY = Regex.Match(text[r], #"Y([0-9\.]+)");
GroupCollection posXGroup = posX.Groups;
GroupCollection posYGroup = posY.Groups;
Console.WriteLine(posXGroup[1] + "\t" + posYGroup[1] + "\n");
sb.Append(posXGroup[1]);
sb.Append("\t");
sb.Append(posYGroup[1]);
sb.Append("\n");
}
}
richTextBox2.Text = sb.ToString();
}
To see why this is happening put a breakpoint on the line richTextBox2.Text = then step through the code pressing F10, each iteration of the loop will reset the richTextBox2.Text's value.
You're assigning over the top. You need to assign by concatenating to append the text. It doesn't matter if the text has new lines. Assignment = will set the variable to the Text property. Addition assignment operator += will concatenate.

Use i in variable name

So I have this kind of code (I'm assigning values to XAML elements
), which begs for a "for" loop.
Day1d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(1));
Day2d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(2));
Day3d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(3));
Day4d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(4));
Day1t.Text = "°" + (myWeatherForecast.forecastlist[1].temp).ToString();
Day2t.Text = "°" + (myWeatherForecast.forecastlist[2].temp).ToString();
Day3t.Text = "°" + (myWeatherForecast.forecastlist[3].temp).ToString();
Day4t.Text = "°" + (myWeatherForecast.forecastlist[4].temp).ToString();
But all my attempts to include "i" in variable name failed miserably. Is there a way to achieve this?
You can create a loop where you iterate over the instances:
int counter = 1; // are you sure it shouldn't start at 0?
foreach (TextBox tb in new TextBox[] { Day1d, Day2d, Day3d, Day4d })
{
tb.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(counter));
counter++;
}
counter = 1;
foreach (TextBox tb in new TextBox[] { Day1t, Day2t, Day3t, Day4t })
{
tb.Text = "°" + (myWeatherForecast.forecastlist[counter].temp).ToString();
counter++;
}
You can't compose the name of the variable using another variable. The way to do this would be to create a List and then iterate over that List
var textBoxes1 = new List<TextBox> { Day1d, Day2d, Day3d, Day4d }
var textBoxes2 = new List<TextBox> { Day1t, Day2t, Day3t, Day4t }
foreach (var textbox in textBoxes1)
{
var index = textBoxes1.IndexOf(textBox) + 1;
textbox.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(index));
}
foreach (var textbox in textBoxes2)
{
var index = textBoxes2.IndexOf(textBox) + 1;
textbox.Text = "°" + (myWeatherForecast.forecastlist[index].temp).ToString();
}
NOTE: You can solve this in different ways:
using arrays instead of lists
keeping your own counter, instead of doing IndexOf
using a for loop, instead of a foreach
Which one is better is mostly based on opinion (although my method is not the fastest, but it doesn't matter if you only have 4 items)
You can use FindName assuming you are using WPF.
Try:
for (int i = 1; i < 5; i++)
{
((TextBox)this.FindName("Day" + i + "d")).Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(i));
((TextBox)this.FindName("Day" + i + "t")).Text = "°" + (myWeatherForecast.forecastlist[i].temp).ToString();
}

C# sort values from textboxes from min to max

I want to take the values from my textboxes when I press the FIFO button, detect the smallest one and do the operations starting with the smallest number in ti and t until the biggest one, then store all that in tf.
This is what my program looks like:
Here's my code:
private void fifo_Click(object sender, EventArgs e)
{
int c = 0;
//Hace tf
tfA.Text = (Convert.ToInt32(ta.Text) + Convert.ToInt32(tiA.Text)).ToString();
c = Convert.ToInt32(tfA.Text);
tfB.Text = (Convert.ToInt32(tb.Text) + c).ToString();
c = Convert.ToInt32(tfB.Text);
tfC.Text = (Convert.ToInt32(tc.Text) + c).ToString();
c = Convert.ToInt32(tfC.Text);
tfD.Text = (Convert.ToInt32(td.Text) + c).ToString();
c = Convert.ToInt32(tfD.Text);
tfE.Text = (Convert.ToInt32(te.Text) + c).ToString();
c = Convert.ToInt32(tfE.Text);
tfF.Text = (Convert.ToInt32(tf.Text) + c).ToString();
// Hace T
T1.Text = (Convert.ToInt32(tfA.Text) - Convert.ToInt32(tiA.Text)).ToString();
T2.Text = (Convert.ToInt32(tfB.Text) - Convert.ToInt32(tiB.Text)).ToString();
T3.Text = (Convert.ToInt32(tfC.Text) - Convert.ToInt32(tiC.Text)).ToString();
T4.Text = (Convert.ToInt32(tfD.Text) - Convert.ToInt32(tiD.Text)).ToString();
T5.Text = (Convert.ToInt32(tfE.Text) - Convert.ToInt32(tiE.Text)).ToString();
T6.Text = (Convert.ToInt32(tfF.Text) - Convert.ToInt32(tiF.Text)).ToString();
// Hace E
E1.Text = (Convert.ToInt32(T1.Text) - Convert.ToInt32(ta.Text)).ToString();
E2.Text = (Convert.ToInt32(T2.Text) - Convert.ToInt32(tb.Text)).ToString();
E3.Text = (Convert.ToInt32(T3.Text) - Convert.ToInt32(tc.Text)).ToString();
E4.Text = (Convert.ToInt32(T4.Text) - Convert.ToInt32(td.Text)).ToString();
E5.Text = (Convert.ToInt32(T5.Text) - Convert.ToInt32(te.Text)).ToString();
E6.Text = (Convert.ToInt32(T6.Text) - Convert.ToInt32(tf.Text)).ToString();
//Hace I
I1.Text = (Convert.ToDecimal(ta.Text) / Convert.ToDecimal(T1.Text)).ToString();
I2.Text = (Convert.ToDecimal(tb.Text) / Convert.ToDecimal(T2.Text)).ToString();
I3.Text = (Convert.ToDecimal(tc.Text) / Convert.ToDecimal(T3.Text)).ToString();
I4.Text = (Convert.ToDecimal(td.Text) / Convert.ToDecimal(T4.Text)).ToString();
I5.Text = (Convert.ToDecimal(te.Text) / Convert.ToDecimal(T5.Text)).ToString();
I6.Text = (Convert.ToDecimal(tf.Text) / Convert.ToDecimal(T6.Text)).ToString();
//X1 2 y 3
X1.Text = ((Convert.ToDecimal(T1.Text) + Convert.ToDecimal(T2.Text) + Convert.ToDecimal(T3.Text) + Convert.ToDecimal(T4.Text) + Convert.ToDecimal(T5.Text) + Convert.ToDecimal(T6.Text)) / 6).ToString();
X2.Text = ((Convert.ToDecimal(E1.Text) + Convert.ToDecimal(E2.Text) + Convert.ToDecimal(E3.Text) + Convert.ToDecimal(E4.Text) + Convert.ToDecimal(E5.Text) + Convert.ToDecimal(E6.Text)) / 6).ToString();
X3.Text = ((Convert.ToDecimal(I1.Text) + Convert.ToDecimal(I2.Text) + Convert.ToDecimal(I3.Text) + Convert.ToDecimal(I4.Text) + Convert.ToDecimal(I5.Text) + Convert.ToDecimal(I6.Text)) / 6).ToString();
comp1 = Convert.ToDecimal(X3.Text);
}
EDIT: I managed to do what I wanted. I just put the values in an array and sorted them, then equaled the textbox.Text to each one. Worked pretty well. Thank you for the help.
My suggestion would be:
// list holding the ti value and the three controls: ti, t and tf
var controls = new List<Tuple<int, Control, Control, Control>>();
// add all the controls together with the sorting key, the ti value (just an example, but here you add the tiValue and the ti control, t control and tf control
controls.Add(new Tuple<int, Control, Control, Control>(0, null, null, null));
// sort everything
controls.Sort((t1, t2) => t1.Item1.CompareTo(t2.Item1));
// loop through the controls in the right order and perform the logic
foreach (var t in controls)
{
var tiValue = t.Item1;
var tiControl = t.Item2;
var tControl = t.Item3;
var tfControl = t.Item4;
// Do the things to the controls and their values...
}
Can't access pastebin or imgur where I am but I'll give this a shot. Textboxes are a terrible idea for this though.
public static void SortAndSumTextboxes()
{
Form form = new Form();
var tiControls = form.Controls.OfType<TextBox>().Where(tb => Regex.IsMatch(tb.Name, "^ti.$"));
var tControls = form.Controls.OfType<TextBox>().Where(tb => Regex.IsMatch(tb.Name, "^t.$"));
var tiSorted = tiControls.Select(tb => int.Parse(tb.Text)).OrderBy(i => i);
var tSorted = tControls.Select(tb => int.Parse(tb.Text)).OrderBy(i => i);
int c = 1; // some constant
var tfValues = tiSorted.Zip(tSorted, (a, b) => a + b + c).ToArray();
var tfControls = form.Controls.OfType<TextBox>().Where(tb => tb.Name.StartsWith("tf")).OrderBy(tb => tb.Name).ToArray(); ;
for (int i = 0; i < tfControls.Length; i++)
{
tfControls[i].Text = tfValues[i].ToString();
}
}

How to access labels from loop and change their text

I have list where are 6 sentences which I want to put in 6 different labels.
All six labels are named Slot0Sentence, Slot1Sentence, Slot2Sentence...
This is how I loop
for (int i = 0; i < ls.Count; i++)
{
Slot0Sentence.Text = ls[i];
}
However I dont know how to access other labels.
If there would be normal string I would do Slot + i + Sentence but in this case this dont work.
with an array of labels you can control their properties. you don't need design here, you can do that with code.
Label[] l = new Label[6];
int x = 20;
for (int i = 0; i < l.Length; i++)
{
l[i] = new Label();
l[i].Name = "Hello " + i.ToString();
l[i].Text = "Hello " + i.ToString();
l[i].Location = new Point(x, 10);
x += 100;
}
you can change the names and text to whatever you like.
I'd just use Children property of parent container (Grid, StackPanel,..). This gives you a collection which supports indexes. Additionally, in case you have different controls, use if statement
if(element in Label)
{
element.Text = ...
}

Calculating average with SelectedIndices

My program reads coordinates(double x,douule y) into ListBox and need to calculate the average of them after choosing them with SelectedIndices and MultiExtended.
The problem is how can I refresh my code with each Multiselection.
As you can see I set SelectedIndices[0] to 0 as default. At the moment my program just making average of the 1st coordinate divided by number of selectedIndices.
If you think about any ways to improve my code I would like to know as well.
Thanks!
private void button3_Click(object sender, EventArgs e)//Average
{
int[] selected = new int[] {points_List.SelectedIndices[0] };
double sumX = 0, sumY = 0; ;
foreach (int iIndex in selected)
{
sumX += points[iIndex].X;
sumY += points[iIndex].Y;
}
averageX = (sumX) / (points_List.SelectedIndices.Count);
averageY = (sumY) / (points_List.SelectedIndices.Count);
label1.Text = "Average is: ";
label1.Text += averageX.ToString();
label1.Text += " ";
label1.Text += averageY.ToString();
}
The correct code will require a cast of SelectedIndices through OfType<T> or Cast<T>. Also, it's convenient to call ToArray to materialize the result to avoid having to compute it twice.
var selectedPoints = points_List.SelectedIndices.
OfType<int>().
Select(i => points[i]).
ToArray();
var averageX = selectedPoints.Average(p => p.X);
var averageY = selectedPoints.Average(p => p.Y);
Final solution, Thanks all.
{
double averageX = 0, averageY = 0;
var selectedPoints = from int i in pointsList.SelectedIndices select points[i];
if (pointsList.SelectedIndices.Count == 0)
{
label1.Text = "Average is 0.000 0.000 ";//default text
return;
}
averageX = selectedPoints.Average(p => p.X);
averageY = selectedPoints.Average(p => p.Y);
label1.Text = "Average X: ";
label1.Text += averageX.ToString();
label1.Text += " Y:";
label1.Text += averageY.ToString();
}

Categories

Resources