I am creating calculator with 20 textboxes - 10 for input, 10 for output. After creating a method into which I put parameter(defined in the first 10 textboxes) I return value to main method.
To get all 10 values is it really necessary to write code for all 10 or more text boxes as I have already started or there is smarter way how to pass into the method textbox parameters and return multiple values at once?
UPDATE:
As you recomended I created List of Tuples and used foreach loop to loop through them, but now i get error:
Error 1 Cannot implicitly convert type 'int' to 'string'. Could you help me to point out where the problem is?
private void button1_Click(object sender, EventArgs e)
{
List<Tuple<TextBox,TextBox>> tuple1 = new List<Tuple<TextBox,TextBox>>();
tuple1.Add(Tuple.Create(textBox1, textBox2));
tuple1.Add(Tuple.Create(textBox3, textBox4));
tuple1.Add(Tuple.Create(textBox5, textBox6));
tuple1.Add(Tuple.Create(textBox7, textBox8));
foreach (Tuple<TextBox,TextBox> box in tuple1)
{
var inputBox = box.Item1;
var outputBox = box.Item2;
outputBox.Text = MethodA(Convert.ToInt32(inputBox.Text));
}
}
private int MethodA(int Parameter1)
{
int A = Parameter1;
int B = 20;
int C;
if (A == 16 && B == 20) { C = 15; } else if (A == 20 && B == 20) { C = 25; } else { C = 0; };
return C;
}
You could store all the input-output textbox combination in the constructor:
private List<Tuple<TextBox, TextBox>> textBoxes = new List<Tuple<TextBox, TextBox>>();
public Form1() {
InitializeComponents();
textBoxes.add(Tuple.Create(textBox1, textBox4);
// ...
}
And then, in button1_Click, just iterate over all the textboxes:
foreach (Tuple<TextBox, TextBox> boxes in textBoxes) {
var inputBox = boxes.Item1;
var outputBox = boxes.Item2;
outputBox.Text = MethodA(Convert.ToInt32(inputBox.Text));
}
This might not be the best answer, but it would work:
public class Extensions
{
public MethodA(this TextBox tb)
{
tb.Text = (Convert.ToInt32(tb.Text) + 5).ToString();
}
}
now you can just call:
textBox1.MethodA();
textBox2.MethodA();
...etc.
This isn't necessarily recommended, but it's one way you could simply doing this multiple times.
If you won't be repeating this, it'd probably be better to just inline the logic the same way:
textBox1.Text = (Convert.ToInt32(textBox1.Text) + 5).ToString();
textBox2.Text = (Convert.ToInt32(textBox2.Text) + 5).ToString();
textBox3.Text = (Convert.ToInt32(textBox3.Text) + 5).ToString();
Related
How would I stop text changed from running if statement? because after I type {} the code runs, but if I type any letter or press enter after I type {} the code keeps on making new labels in every letter typed or entered.
This is for WPF c#
private void TextBox_TextChanged(object sender, EventArgs e)
{
if (textBox.Text.Contains("{") && textBox.Text.Contains("}"))
{
DraggableLabel ag = new DraggableLabel();
ag.Name = "A";
ag.Content = "you have bracket"; //(i + 1).ToString();
ag.BorderBrush = Brushes.Black;
ag.BorderThickness = new Thickness(2, 2, 2, 2);
DesigningCanvas.Children.Add(ag);
ab = ag;
}
}
Notwithstanding the comments about avoiding creating UI elements in event handlers, what you need is a system that only activates if there are new { } pairs in the textbox. Perhaps something like:
private int brasProcessed = 0;
private void TextBox_TextChanged(object sender, EventArgs e)
{
int countOpenBra = textBox.Text.Count(c => c == '{');
int countCloseBra = textBox.Text.Count(c => c == '}');
//if there is a matched pair of {} (equal counts) and more { have appeared than we know we've processed before...
if (countOpenBra == countCloseBra && countOpenBra > brasProcessed)
{
DraggableLabel ag = new DraggableLabel();
ag.Name = "A";
ag.Content = "you have bracket"; //(i + 1).ToString();
ag.BorderBrush = Brushes.Black;
ag.BorderThickness = new Thickness(2, 2, 2, 2);
DesigningCanvas.Children.Add(ag);
ab = ag;
//mark the current count of {} as processed so the code will not fire again until someone adds a new { } pair
brasProcessed = countOpenBra;
}
}
Now this code will only fire when new pairs of { } are added. Every time you add a { } pair the code will run. It does not cater for deleted. It does not cater for multiples if a large amount of text containing multiple { } is pasted in. It hence likely needs some improvement but as others have noted you didn't tell us what you were trying to do, only that your solution for it was broken, and alas the solution didn't really allow us to infer what you're trying to do
Someone here at works needs some calculations done from some numbers within a text file. I know how to do the calculation but I haven't worked with text file before. So I spent the night reading and wrote a little something for the first number I needed but it doesn't work.
So here is an example of the file.
So that first number that comes after FSD: 0.264 I need to read that number and save to a variable. The number will always be different per file. Then I need the first 3.4572 number read to a variable. and the last number of that column as well which you don't see here but for the example it can be the last one shown in the image of 3.3852 read and saved to a variable.
Maybe I'm making this much harder than it needs to be but this is what I was playing around with
public partial class FrmTravelTime : Form
{
string file = "";
public FrmTravelTime()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
file = openFileDialog1.FileName;
}
}
private void button2_Click(object sender, EventArgs e)
{
var sLines = File.ReadAllLines(file)
.Where(s => !s.StartsWith("FSD:"))
.Where(s => !string.IsNullOrWhiteSpace(s))
.Select(s => new
{
SValue = Regex.Match(s, "(?<=S)[\\d.]*").Value,
})
.ToArray();
string Value = "";
for (int i = 0; i < sLines.Length; i++)
{
if (sLines[i].SValue == "")
{
Value = (sLines[i].SValue);
}
}
}
}
EDIT FOR #Ramankingdom
So if you see here all lines have an ending column of 0.00 until we get to
3.0164 7793 1 0 0.159 0.02
So what I'd like to do, is edit what we did to skip everything that has a column with 0.00 in that last column and make the first non 0.00 the info.firstvalue so in this case 3.0164
Now I tried this on my own and used
var data = lines.Where(line => (!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
But that breaks info.startvalue and data = dataWithAvgVolts[dataWithAvgVolts.Count - 1].Split(splitter);
So I'd figured I'd check with you.
So I tried this but I keep getting invalid data error on info.startvalue
FileInfo info = new FileInfo();
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var fsdLine = lines.FirstOrDefault(line =>
line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 7);
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList();
int index =1;
while(index < dataWithAvgVolts.Count())
{
var data = dataWithAvgVolts[index].Split(splitter);
if(data.Count() >1)
{
if(!Convert.ToDouble(data[data.Count()-1]) == 0)
{
//set start info
break;
}
}
index++;
}
the reverse loop you can run to set the end value
Here is the code
class Program
{
const string FSD_Identifier = "FSD:";
const string FSD__Line_Identifier = "Drilling Data";
const string Data_Start_Point_Identifier = "AVG_VOLTS";
static readonly char[] splitter = {' ','\t'};
static void Main(string[] args)
{
var result = GetFileInfo("c:\\sample.txt");
}
private static MyFileInfo GetFileInfo(string path)
{
MyFileInfo info = new MyFileInfo();
try
{
var lines = File.ReadAllLines(path);
var fsdLine = lines.FirstOrDefault(line => line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 10); // take lenght you can specify or your own logic
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList<string>();
if (dataWithAvgVolts.Count() > 1)
{
var data = dataWithAvgVolts[1].Split(splitter);
info.startvalue = Convert.ToDouble(data[0]);
data = dataWithAvgVolts[dataWithAvgVolts.Count-1].Split(splitter);
info.endvalue = Convert.ToDouble(data[0]);
}
}
catch (Exception ex)
{
//logging here
}
return info;
}
}
public class MyFileInfo
{
public string FSD;
public double startvalue;
public double endvalue;
}
Right now my code has 52 checkboxes that each return their own value.
if (checkedListBox1.GetItemCheckState(0) == CheckState.Checked)
{
x += 1;
}
if (checkedListBox1.GetItemCheckState(1) == CheckState.Checked)
{
x += 2;
}
if (checkedListBox1.GetItemCheckState(2) == CheckState.Checked)
{
x += 1;
}
I want to group if statements that do the same thing into a single statement, something like
if (checkedListBox1.GetItemCheckState(0) == CheckState.Checked ||
checkedListBox1.GetItemCheckState(2) == CheckState.Checked ||
checkedListBox1.GetItemCheckState(17) == CheckState.Checked )
{
x += 1;
}
However such a code would only run once. Is there an operator that would help in this situation or would I have to just write 52 if statements.
I would create an int[] array of scores with one entry for each possible checkbox:
var scores = new []
{
1,
2,
1,
4,
2,
1,
// Etc up to 52 items
};
Then you can just loop though all the checkboxes and add up all the scores:
for (int i = 0; i < checkedListBox1.Items.Count; ++i)
if (checkedListBox1.GetItemCheckState(i)) == CheckState.Checked)
x += scores[i];
You could also use CheckedListBox.CheckedIndices to iterate through the checked items, which would look like this:
x = checkedListBox1.CheckedIndices.Cast<int>().Sum(i=> scores[i]);
A much better way to approach this, IMO, is to write a special Yaku class which is used to hold information about each item in the list. This would include the name and the score (han). It would also override ToString() so that the name would be displayed in the list.
It could look a bit like this:
public class Yaku
{
public string Name { get; }
public int Han { get; }
public Yaku(string name, int han)
{
Name = name;
Han = han;
}
public override string ToString()
{
return Name;
}
}
Then you could initialise the checked list box somewhere like this:
public Form1()
{
InitializeComponent();
checkedListBox1.Items.Add(new Yaku("Little three dragons", 4));
checkedListBox1.Items.Add(new Yaku("Terminal in each set", 3));
checkedListBox1.Items.Add(new Yaku("Three closed triplets", 3));
}
And add up the scores like this:
private void button1_Click(object sender, EventArgs e)
{
int score = checkedListBox1.CheckedItems.OfType<Yaku>().Sum(item => item.Han);
MessageBox.Show(score.ToString());
}
Put the indices of checkboxes in a list / array:
using System.Linq;
...
var checkboxIndices = { 0, 2, 17 };
x += checkboxIndices.Count(index =>
checkedListBox1.GetItemCheckState(index) == CheckState.Checked);
Edit: Sigh, I though it was obvious but here's the same thing with more details:
class Yaku
{
public Yaku(List<int> indices, int han)
{
Indices = indices;
HanValue = han;
}
public List<int> Indices;
public int HanValue;
public int ComputeValue(CheckedListBox checkedListBox)
{
return HanValue * Indices.Count(index =>
checkedListBox.GetItemCheckState(index) == CheckState.Checked);
}
}
...
var yakus = [
new Yaku({0, 2, 17 }, 1),
new Yaku({1}, 2)
...
];
var totalYakuValue = yakus.Aggregate(yaku => yaku.ComputeValue());
I'm working on a program that allows you to select a customer ID from a dropdown box. Once the customer ID is selected, the customer's information is pulled from a CSV file and displayed in textboxes.
The phone number information is unformatted, but I want it to be displayed formatted (ex. (800)674-3452). I have written a method for this, but I'm not sure how to call it. Can you please help?
-Sorry if this is a dumb question. I'm still learning.
private void idBox_SelectedIndexChanged(object sender, EventArgs e)
{
try // catch errors
{
string selectedCustomer; // variable to hold chosen customer ID
selectedCustomer = idBox.Text; // retrieve the customer number selected
chosenIndex = 0;
bool found = false; // variable if customer ID was found
while (!found && chosenIndex < allData.Length) // loop through the 2D array
{
if (allData[chosenIndex, 0] == selectedCustomer) // make sure it's the right customer
{
found = true; // Yes (true) found the correct customer
}
chosenIndex++; // add one row
}
chosenIndex -= 1; // subtract one because add 1 before exiting while
/* 0 = customer ID
* 1 = name
* 2 = address
* 3 = city
* 4 = state
* 5 = zip
* 6 = phone
* 7 = email
* 8 = charge account - yes/no
* 9 = good standing - yes/no
*/
nameBox.Text = allData[chosenIndex, 1]; // put name in nameBox
addressBox.Text = allData[chosenIndex, 2]; // put address in addressBox
cityBox.Text = allData[chosenIndex, 3]; // put city in cityBox
stateBox.Text = allData[chosenIndex, 4]; //puts state in stateBox
zipBox.Text = allData[chosenIndex, 5]; // puts zip in zipBox
phoneBox.Text = allData[chosenIndex, 6]; // puts phone number in phoneBox
emailBox.Text = allData[chosenIndex, 7]; // puts email in emailBox
if (allData[chosenIndex, 8] == "Yes") // check if charge account
{
yesChargeRadio.Checked = true; // true if Yes
}
else // otherwise
{
noChargeRadio.Checked = true; // true if No
}
if (allData[chosenIndex, 9] == "Yes") // check for good standing
{
yesStandingRadio.Checked = true; // true if Yes
}
else // otherwise
{
noStandingRadio.Checked = true; // true if No
}
}
catch (Exception errorInfo) // catch error
{
MessageBox.Show("errors: " + errorInfo, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error); // error message
}
}
Here is the method(s) to check the length and format:
private bool numberCheck(string str)
{
const int NUMBER_LENGTH = 10;
bool valid = true;
if (str.Length == NUMBER_LENGTH)
{
foreach (char ch in str)
{
if (!char.IsDigit(ch))
{
valid = false;
}
}
}
else
{
valid = false;
}
return valid;
}
private void formatPhone(ref string str)
{
str = str.Insert(0, "(");
str = str.Insert(4, ")");
str = str.Insert(8, "-");
}
You are almost done with your code. What you need to do is, before you set your phoneBox.Text you can call the method as below:
if(numberCheck(allData[chosenIndex, 6]))
{
formatPhone(ref allData[chosenIndex, 6]);
}
phoneBox.Text = allData[chosenIndex, 6];
As you have your method with ref parameter, the formatted text will be updated in your arary and you can then assign it to your phoneBox
I hope I understand what part specifically you're asking about: you call methods you define just like the static methods IsDigit or MessageBox.Show, except you do not need to prefix the method name with a name and then a period because the method is part of the object calling it.
So, for example if I had a method:
public void ShowSomething()
{
MessageBox.Show("stuff");
}
From within the class, I could call it like this:
ShowSomething();
To pass parameters, I would list them in the parenthesis, as you do with MessageBox.Show, for example.
You can use the value a method like numberCheck returns as any other boolean, so you could do any of these:
bool b = numberCheck(someString);
if (numberCheck(someString))
{
//Do something, like displaying the phone number
}
This MSDN document might help you: http://msdn.microsoft.com/en-us/library/ms173114.aspx
Is this what you're looking for? :
.......
phoneBox.Text = numberCheck(allData[chosenIndex, 6]) ?
formatPhone(allData[chosenIndex, 6]) :
allData[chosenIndex, 6];
.......
private string formatPhone(string str)
{
str = str.Insert(0, "(");
str = str.Insert(4, ")");
str = str.Insert(8, "-");
return str;
}
Codes above will check validity of phone data, if it is valid set phoneBox.Text to formatted phone number, else set phoneBox.Text to raw unformatted phone data.
For reference in case you're not familiar with ternary operator (?).
This is homework (I always try to point that out so it's up front). The program is a conversion program. The user picks a conversion option from a combo box and then enters a length (ie: Feet to meters) when the user hits calculate the program calculates the conversion. I have several questions because the array part is confusing me. I wanted to make sure I am going in the right direction.
I think I am using my array to populate my combo box (I used an example provided although I do not fully understand it). When the user hits the calculate button should I be storing my conversion values in the same array? something like:
string [,] conversions = { {kilometers to miles, .11111}, {miles to kilometers, .11111}}
Or am I heading in the right direction with what I have? To be clear as it is coded the array populates my combobox so if I add the extra data then it will display those numbers in the combobox, which isn't really what I am going for.
My next question, when the user hits calculate button how is it going to know what option the user has selected? I think it has something to do with index but I'm confused as far as what is actually declaring it?
*****Disregard this question. I think I found an answer*********
Answer on Updating Labels
Finally I think my last question is the page has labels next to the textboxes so if the user chooses 'Miles to kilometers" the entry textbox is going to say Miles and then the answer textbox would say Kilometers... What is that called? I need to find it in my book and cannot. I know I'm missing something but I'm trying to find either an example or where in the book it was covered and I'm simply not seeing it.
Below is my code that I currently have.
public partial class FrmConversions : Form
{
const double Miles_To_Kilometers = 1.6093;
const double Kilometers_To_Miles = 0.6214;
const double Feet_To_Meters = 0.3048;
const double Meters_To_Feet = 3.2808;
const double Inches_To_Centimeters = 2.54;
const double Centimeters_To_Inches = 0.3937;
public FrmConversions()
{
InitializeComponent();
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void FrmConversions_Load(object sender, EventArgs e)
{
cboConversions.Items.Clear(); //clear the combobox
string[,] conversions =
{
{"Kilometers to Miles" , "Miles to Kilometers"},
{"Feet to Meters" , "Meters to Feet"},
{"Inches to Centimeters", "Centimeters to Inches"}
};
foreach (string str in conversions)
{
cboConversions.Items.Add(str);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
txtEntry.Clear();
txtAnswer.Clear();
}
public bool IsDecimal(TextBox txtEntry, string name)
{
try
{
Convert.ToDecimal(txtEntry.Text);
return true;
}
catch (FormatException)
{
MessageBox.Show(name + " must be a decimal value.", "Entry Error");
txtEntry.Focus();
return false;
}
}
private void btnCalculate_Click(object sender, EventArgs e)
{
int index = cboConversions.SelectedIndex;
if (index != -1)
{
try
{
if (IsDecimal())
{
txtAnswer.Text = ToString;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" +
ex.GetType().ToString() + "\n" +
ex.StackTrace, "exception");
}
}
}
}
}
}
There are many ways to do this, a Dictionary would be neat?
In this example, the Keys of the dictionary (the strings I specified) are loaded into the combo box. Later, those strings can be used to retrieve the conversion value from the dictionary.
// Declare at the top
Dictionary<string, double> conversions = {
{ "Kilometers to Miles", Kilometers_To_Miles},
{ "Miles to Kilometers", 1 / Kilometers_To_Miles},
{ "Feet to Meters", Feet_To_Meters},
{ "Meters to Feet", 1 / Feet_To_Meters},
etc
};
// In Form Load
foreach (string str in conversions.Keys)
{
cboConversions.Items.Add(str);
}
// In btnCalculate_Click
var conversionValue = conversions[cboConversions.Text];
var convertedValue = (double)txtEntry.Text * conversionValue; // Need to validate is numeric
txtAnswer.Text = convertedValue
If you were hellbent on using arrays then this would work too, but cheats by using LINQ at the end:
// Declare at the top
object[,] conversions = {
{ "Kilometers to Miles", Kilometers_To_Miles},
{ "Miles to Kilometers", 1 / Kilometers_To_Miles},
{ "Feet to Meters", Feet_To_Meters},
{ "Meters to Feet", 1 / Feet_To_Meters},
etc
};
// In Form Load
foreach (string str in conversions)
{
cboConversions.Items.Add(str[0]);
}
// In btnCalculate_Click
var conversionValue = conversions.First(x => x[0] == cboConventions.Text)[1];
var convertedValue = (double)txtEntry.Text * conversionValue; // Need to validate is numeric
txtAnswer.Text = convertedValue