Creating automatic labels in form to display value from database - c#

Was trying out a simple FB API app to retrieve status.
So what i am intending to do is to perform a word check with my dictionary.
I have a database which stores emotive data on the feeling % and the genre of the feeling.
If the status contains the emotive word, i wish to perform a word analysis.
For instance: "I am feeling sad and angry"
So what i want it to display is like...
"Username"
was feeling
50% angry
and 25% sad.
*% is calculated by random function.
However, i think its impossible for me to keep creating labels. What if my status has > 5 emotions? Is it possible to create automatic labels which would display the output?
Below is my code:
private void EmotionAnalysis_Load(object sender, EventArgs e)
{
label1.Text = tpc.loadInfo(currentId)["target_name"].ToString();
//List<DataRow> result = dict.AngerPercent(fbStatus);
CalculateAndDisplayAnalysis("Angry", topPercentLabel, topFeelingLabel);
CalculateAndDisplayAnalysis("Caring", bottomPercentLabel, bottomFeelingLabel);
//var item = new ListViewItem(new[] { "", String.Format("{0}%", percent.ToString()), result[0]["Genre"].ToString() });
//listViewEmotion.Items.Add(item);
}
private void CalculateAndDisplayAnalysis(string genre, Label percentLabel, Label feelingLabel)
{
List<DataRow> result = dict.GenrePercent(fbStatus, genre);
var rnd = new Random();
int total = 0;
for (int i = 0; i < result.Count; i++)
{
total += rnd.Next(Convert.ToInt32(result[i]["Min_Percentage"]), Convert.ToInt32(result[i]["Max_Percentage"]));
}
if (result.Count != 0)
{
int percent = total / result.Count;
percentLabel.Text = String.Format("{0}%", percent.ToString());
feelingLabel.Text = result[0]["Genre"].ToString();
}
}

You can create as many labels as you want. you just need to set the position of the label and add it to the forms Controls enumeration:
Label lbl = new Label();
lbl.Text = "MyText";
lbl.Location = new Position(xPos, yPos);
this.Controls.Add(lbl);
You will have to keep track of the new position which is in this case determined by xPos and yPos

Related

Set caret at an index in RichTextBox WPF

I am trying to set the position of caret in richtextbox based on index position of a word. Even though I am able to change the caret position, the caret does not move to the correct location.
Here is my sample code:
private void Button_Click(object sender, RoutedEventArgs e)
{
RTB_Main.Document.Blocks.Clear();
for (int i = 0; i < 10; i++)
{
Paragraph para = new Paragraph(new Run(i + ""));
RTB_Main.Document.Blocks.Add(para);
}
TextRange richText = new TextRange(RTB_Main.Document.ContentStart, RTB_Main.Document.ContentEnd);
string searchText = tb_Search.Text; // 1 to 9
int position = Regex.Match(richText.Text, searchText).Index;
RTB_Main.CaretPosition = RTB_Main.Document.ContentStart;
RTB_Main.CaretPosition = RTB_Main.CaretPosition.GetPositionAtOffset(position);
RTB_Main.Focus();
}
What is wrong with this approach?
Also, Please let me know if there is a better way to set the caret position to an index?
The problem in my case was caused by new line characters \r\n. I just replaced these with another characters and it worked for me. Note that I am replacing them with not 2 characters but 4.
private void Button_Click(object sender, RoutedEventArgs e)
{
RTB_Main.Document.Blocks.Clear();
for (int i = 0; i < 10; i++)
{
Paragraph para = new Paragraph(new Run(i + ""));
RTB_Main.Document.Blocks.Add(para);
}
TextRange richText = new TextRange(RTB_Main.Document.ContentStart, RTB_Main.Document.ContentEnd);
string searchText = tb_Search.Text; // 1 to 9
string tmpStr = richText.Text.Replace("\r\n", "....");
int position = Regex.Match(tmpStr, searchText).Index;
RTB_Main.CaretPosition = RTB_Main.Document.ContentStart;
RTB_Main.CaretPosition = RTB_Main.CaretPosition.GetPositionAtOffset(position);
RTB_Main.Focus();
}
As Maciek noted, there are invisible formatting items that affects the count. My code adds a feedback loop because we are able to ask what the true caret position is. It feels hacky but I could not find anything better.
public static void SetCaretPositionOfRichTextBoxToCharIndex(
System.Windows.Controls.RichTextBox box, int charIndex)
{
// RichTextBox contains many formattings, and they, although invisible, count
// when setting CaretPosition. Calling GetPositionAtOffset with charIndex from
// DocumentStart can be less than the necessary CaretPosition. This code
// therefore has a feedback loop to see how much more offset is necessary.
box.CaretPosition = box.CaretPosition.DocumentStart;
int attemptedCharIndex = 0;
int fixerInc = 0;
while (attemptedCharIndex < charIndex)
{
box.CaretPosition = box.CaretPosition.GetPositionAtOffset(charIndex - attemptedCharIndex + fixerInc);
int temp = new TextRange(box.Document.ContentStart, box.CaretPosition).Text.Length;
if (attemptedCharIndex == temp)
{
fixerInc++;
}
else
{
fixerInc = 0
}
attemptedCharIndex = temp;
}
}

C# - Chart.Series[index].Points.Label not producing any label of datapoint

I have a chart which has 9 different series to it, only two of which can ever be enabled at the same time.
My user has asked that when the first datapoint is added to the chart, it is labelled 'Start', and this enables the button that will then allow the user to mark 'End'.
During the development of the solution, this wasn't a problem as I had control over which of the series were enabled at any one time. Now the facility has been added for the user to change this in the 'Options' menu (series name and enabled state written to 'Settings' file, to then be read in next time the program begins.
In order to try and do this, I created a List<> 'enabledSeries' in my updateChart function that finds the enabled of the chart series and adds them to the list. This has been done fine, and adding datapoints to the chart works using this method. For some reason, however, Labels now do not appear at the start of each series.
The code for updateChart() and subfunctions is shown below:
public void updateChart(int minutesElapsed)
{
//int latestReading = 0; //local variable to hold va1ue from txtBP.Text
chartVitals.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chartVitals.Text = "Vitals Visual";
//Create correct coordinate using reading and time taken
//add newest (last) element in each list to respective chart series, along with value from timer
chartVitals.Series["Heart Rate"].Points.AddXY(minutesElapsed, HRlist.Last());
chartVitals.Series["Ventilation Rate"].Points.AddXY(minutesElapsed, VRlist.Last());
chartVitals.Series["Blood Pressure"].Points.AddXY(minutesElapsed, BPlist.Last());
chartVitals.Series["o2 Saturation"].Points.AddXY(minutesElapsed, BOlist.Last());
chartVitals.Series["ET Co2"].Points.AddXY(minutesElapsed, ETCo2list.Last());
chartVitals.Series["Vaporiser Setting"].Points.AddXY(minutesElapsed, VSlist.Last());
chartVitals.Series["FI Agent"].Points.AddXY(minutesElapsed, FIAlist.Last());
chartVitals.Series["ET Agent"].Points.AddXY(minutesElapsed, ETAlist.Last());
chartVitals.Series["Fresh Gas Flow"].Points.AddXY(minutesElapsed, FGFlist.Last());
//stores all enabled series (MAX 2)
List<string> enabledSeries = new List<string>();
//identify and isolate the enabled series in the chart
identifyEnabled(enabledSeries);
}
public void identifyEnabled(List<string> enabledSeries)
{
//takes name of chart series at current index
string seriesName = "";
//access all items in list
for (int index = 0; index < chartVitals.Series.Count; ++index)
{
//assign name to variable
seriesName = chartVitals.Series[index].Name;
//series with this name is enabled
if (chartVitals.Series[seriesName].Enabled)
{
//add name to list
enabledSeries.Add(seriesName);
}
}
formatEnabled(seriesName, enabledSeries);
}
public void formatEnabled(string seriesName, List<string> enabledSeries)
{
//color series in by index (0 - blue, 1 - red)
string blueSeries = enabledSeries.First();
string redSeries = enabledSeries[enabledSeries.IndexOf(blueSeries) + 1];
//access all elements in enabledSeries
for (int enabledIndex = 0; enabledIndex < enabledSeries.Count; ++enabledIndex)
{
//access all series in chartVitals
for (int seriesIndex = 0; seriesIndex < chartVitals.Series.Count; ++seriesIndex)
{
//when there is item in series
if (chartVitals.Series[seriesName].Points.Count > 0)
{
string start = "[Start]";
//set series type as line
chartVitals.Series[seriesName].ChartType = SeriesChartType.Line;
//apply label to first point of series
chartVitals.Series[seriesName].Points.First().Label = start;
//enable button to mark end
btnOpEnd.Enabled = true;
}
}
}
//apply colours to series
chartVitals.Series[blueSeries].Color = Color.Blue;
chartVitals.Series[redSeries].Color = Color.Red;
}
The code is a bit intricate, but it's commented and should all be there. If anyone can point out what might be causing the problem or a simpler way of doing things, I would really appreciate it!
Thanks,
Mark
Is this what you expected to see?
EDIT: I changed formatEnabled to use seriesIndex instead of seriesName, like below:
public void formatEnabled(string seriesName, List<string> enabledSeries)
{
//color series in by index (0 - blue, 1 - red)
string blueSeries = enabledSeries.First();
string redSeries = enabledSeries[enabledSeries.IndexOf(blueSeries) + 1];
//access all elements in enabledSeries
for (int enabledIndex = 0; enabledIndex < enabledSeries.Count; ++enabledIndex)
{
//access all series in chartVitals
for (int seriesIndex = 0; seriesIndex < chartVitals.Series.Count; ++seriesIndex)
{
//when there is item in series
if (chartVitals.Series[seriesIndex].Points.Count > 0)
{
string start = "[Start]";
//set series type as line
chartVitals.Series[seriesIndex].ChartType = SeriesChartType.Line;
//apply label to first point of series
chartVitals.Series[seriesIndex].Points.First().Label = start;
//enable button to mark end
//btnOpEnd.Enabled = true;
}
}
}
//apply colours to series
chartVitals.Series[blueSeries].Color = Color.Blue;
chartVitals.Series[redSeries].Color = Color.Red;
}

Get value of dynamically created textbox

I'm in a bit of a pickle at the moment, I've created a bit of code that creates 4 textboxes and adds them to a table layout at run time (code below) but I'm struggling with getting text from it, I tried getting the value from it as you would string s = TxtBox1.Text.ToString(); but it just gets a null reference, then I tried txt.Text.ToString();and this just gets the text from the last text box that was created.
private void button2_Click(object sender, EventArgs e)
{
int counter;
for (counter = 1; counter <= 4; counter++)
{
// Output counter every fifth iteration
if (counter % 1 == 0)
{
AddNewTextBox();
}
}
}
public void AddNewTextBox()
{
txt = new TextBox();
tableLayoutPanel1.Controls.Add(txt);
txt.Name = "TxtBox" + this.cLeft.ToString();
txt.Text = "TextBox " + this.cLeft.ToString();
cLeft = cLeft + 1;
}
I've looked all over for the answers to this and as of yet found nothing if anybody has any ideas I would be grateful.
Thanks
this code picks textbox1 from tableLayoutPanel1, cast it from Control to TextBox and takes Text property:
string s = ((TextBox)tableLayoutPanel1.Controls["TxtBox1"]).Text;
if you need them all, then iterate over textboxes:
string[] t = new string[4];
for(int i=0; i<4; i++)
t[i] = ((TextBox)tableLayoutPanel1.Controls["TxtBox"+(i+1).ToString()]).Text;
You can try
var asTexts = tableLayoutPanel1.Controls
.OfType<TextBox>()
.Where(control => control.Name.StartsWith("TxtBox"))
.Select(control => control.Text);
That will enumerate the Text value for all child controls of tableLayoutPanel1 where their type is TextBox and their name starts with "TxtBox".
You can optionally relax the filters removing the OfType line (that excludes any non TextBox control) or the Where line (that allow only the control which name matches your example).
Ensure to have
Using System.Linq;
at the beginning of the file.
Regards,
Daniele.
public void AddNewTextBox()
{
txt = new TextBox();
tableLayoutPanel1.Controls.Add(txt);
txt.Name = "TxtBox" + this.cLeft.ToString();
txt.Text = "TextBox " + this.cLeft.ToString();
cLeft = cLeft + 1;
txt.KeyPress += txt_KeyPress;
}
private void txt_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
//the sender is now the textbox, so that you can access it
System.Windows.Forms.TextBox textbox = sender as System.Windows.Forms.TextBox;
var textOfTextBox = textbox.Text;
doSomethingWithTextFromTextBox(textOfTextBox);
}

Remove Rows from TableLayoutPanel [duplicate]

I'm currently trying to fill a TableLayoutPanel through a method which goes as follows:
private int _rowCount;
public void InitPaths()
{
int c = 1;
int a = 1;
while (a < _PathRows.Length - 1)
{
var label = new Label();
//
// Label - Format.
//
label.Dock = DockStyle.Fill;
label.AutoSize = false;
label.Text = _pfadZeilen[a];
label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
label.Size = new System.Drawing.Size(22, 13);
label.BackColor = System.Drawing.Color.Transparent;
TableLayoutP.Controls.Add(label, 3, c);
//Checkboxen Einfügen
var cbox = new CheckBox();
//
//Checkbox Format.
cbox.Anchor = System.Windows.Forms.AnchorStyles.None;
cbox.AutoSize = true;
cbox.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter;
cbox.Name = "checkBoxPfad" + a;
cbox.Size = new System.Drawing.Size(15, 14);
cbox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
cbox.UseVisualStyleBackColor = true;
TableLayoutP.Controls.Add(cbox, 0, c);
a++;
c++;
}
this._rowCount = BibTable.GetRowHeights().Length; // which seems to be Holding the value only within the method
}
and then delete all rows on Action, through the following Method:
public void RemoveRows()
{
for (int row = _rowCount; row >= 0; row--)
{
BibTable.RowStyles.RemoveAt(row);
BibTable.RowCount--;
}
}
Now the Problem is, if I try to do anything with the TableLayoutP outside of the method where all rows are initialized, it will tell me:
Object reference not set to the instance of an object.
What can I do? Is there a way to get a method inside a method (I'm realising just how stupid that sounds while typing it) or any other way to deal with this Situation?
You are ittering through GetRowHeights(), returning the height of each row. But you are deleting from the RowStyles collection which is not directly related to the first collection. I assume that GetRowHeights() returns much more rows, than RowStyles has.
Why not:
BibTable.RowCount = 0;
BibTable.RowStyles.Clear();
You are ittering through GetRowHeights(), returning the height of each row. But you are deleting from the RowStyles collection which is not directly related to the first collection. I assume that GetRowHeights() returns much more rows, than RowStyles has.
Why not:
BibTable.RowCount = 0;
BibTable.RowStyles.Clear();

How do I take two integer values from a string then put them back into two separate integers?

I have a double dimension string array that holds each buttons specific coordinates
string[,] gridPass = new string[20, 20];
private void Form1_Load(object sender, EventArgs e)
{
foreach (int row in Enumerable.Range(0, 20))
{
foreach (int col in Enumerable.Range(0, 20))
{
Button b = new Button();
b.Size = new System.Drawing.Size(30, 30);
b.Location = new Point(row * 30, col * 30);
gridPass[row, col] = row.ToString() + " - " + col.ToString();
b.Tag = gridPass[row, col];
b.Text = gridPass[row, col];
this.Controls.Add(b);
b.Click += new EventHandler(AttackHandler);
}
}
When I attack using the event handler on my buttons
private void AttackHandler(object sender, EventArgs e)
{
Button clickedButton;
string tagValue = "";
clickedButton = (Button)sender;
tagValue = (string)clickedButton.Tag;
theSea.attackLocation(tagValue);
}
It's obviously sending a string like 0 - 1 or 8 - 4 whatever the button's coordinates are.
When I pass that string to the attackLocation method in my Sea class I want to be able to extract those two numbers to reference them with the array in my Sea class to see if there is a boat there. I Need those X and Y values back to reference the exact same location in another array basically. So I can do something like.
public void attackLocation(string attackCoords)
{
MessageBox.Show("Attacking " + attackCoords);
x = however to convert it back;
y = however to convert it back;
foreach (Ship s in shipList)
{
if (grid[x,y] == 0)
{
MessageBox.Show("Attacked this block before.");
}
Create a class to hold the row and column values and set the Tag to that object. Then you won't need to do string conversions.
class SeaPoint
{
public int Row { get; set; }
public int Column { get; set; }
}
In Load:
foreach (int col in Enumerable.Range(0, 20))
{
Button b = new Button();
b.Size = new System.Drawing.Size(30, 30);
b.Location = new Point(row * 30, col * 30);
gridPass[row, col] = row.ToString() + " - " + col.ToString();
b.Tag = new SeaPoint() { Row = row, Column = col }; // <--- Changed.
b.Text = gridPass[row, col];
this.Controls.Add(b);
b.Click += new EventHandler(AttackHandler);
}
And AttackHandler:
private void AttackHandler(object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
var seaPoint = (SeaPoint)clickedButton.Tag; // <-- Changed
theSea.attackLocation(seaPoint); // rewrite attackLocation to accept a SeaPoint.
}
You can use String.Split to extract the hyphen separated values and apply String.Trim on them to remove the spaces before we pass it to int.Parse to convert string to number.
//b.Tag = "0 - 1";
string []arr = b.Tag.ToString().Split('-');
int num1 = int.Parse(arr[0].Trim());
int num2 = int.Parse(arr[1].Trim());
Make this regular expression:
new Regex(#"(\d+) - (\d+)")
Use the regex's Match on the string you want to extract the numbers from:
http://msdn.microsoft.com/en-us/library/twcw2f1c.aspx
It'll return a Match object, which will contain two groups (assuming I'm remembering the difference between groups and captures right...). The groups' values will be string represenations of the two integers. int.Parse() them.

Categories