Ok, so really weird problem I have here.
When I give ingaveBox a double value (0.5) and i press "bereken", it adds 5.0 to my gespaard variable. I have absolutely no clue how this happens. I know there's a small mistake somewhere but i just can't get it figured out, when I debug the value changes from the moment where i put the comment.
Thanks in advance!
public partial class MainWindow : Window
{
private string path = #"C:\Users\Ragtox\Documents\Spaarpot\Spaarpot\gespaard.txt";
private double vorigGespaard;
private double toegevoegd;
private double gespaard;
public MainWindow()
{
InitializeComponent();
ReadList();
}
void WriteList()
{
string[] createText = {gespaard.ToString()};
File.WriteAllLines(path, createText);
}
void ReadList()
{
string[] readText = File.ReadAllLines(path);
vorigGespaard = Convert.ToDouble(readText[0]);
vorigeBedragBox.Text = readText[0];
}
private void berekenButton_Click(object sender, RoutedEventArgs e)
{
vorigeBedragBox.Text = vorigGespaard.ToString();
gespaard = Convert.ToDouble(ingaveBox.Text) + vorigGespaard;
//this is where 0.5 goes to 5.0
gespaardBox.Text = gespaard.ToString();
WriteList();
ReadList();
}
private void saveButton_Click(object sender, RoutedEventArgs e)
{
WriteList();
}
}
As it's been said, the issue could well stem from the CultureInfo that your machine is running in. In general, you should ALWAYS persist and depersist values in an invariant culture so that values saved in one language can be read in successfully on another language.
Otherwise, if, say a Brazilian Portuguese (language code pt-br) user saves the value "123,456" (which is how one hundred and twenty three and four hundred and fifty six thousandths would be represented in Portuguese), a user reading it in, say, British English (language code en-gb) would interpret it as one hundred and twenty three thousand, four hundred and fifty six (i.e. a factor of one thousand out).
I've modified your code to use Double.ToString(CultureInfo.CurrentCulture) and Double.TryParse to save the values in the invariant culture.
void WriteList()
{
// save in invariant culture
string[] createText = {gespaard.ToString(CultureInfo.CurrentCulture)};
File.WriteAllLines(path, createText);
}
void ReadList()
{
string[] readText = File.ReadAllLines(path);
// read from invariant culture
bool parsed = double.TryParse(readText[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vorigGespaard);
if ( !parsed )
throw new InvalidOperationException("Unable to parse " + readText[0] + " as a double");
// use the current culture to display the string
vorigeBedragBox.Text = vorigGespaard.ToString();
}
private void berekenButton_Click(object sender, RoutedEventArgs e)
{
vorigeBedragBox.Text = vorigGespaard.ToString();
// get the value from its representation in the current culture
gespaard = double.Parse(ingaveBox.Text) + vorigGespaard;
// use the current culture to display the string
gespaardBox.Text = gespaard.ToString();
WriteList();
ReadList();
}
This is a minor inconvenience compared to a real problem I have seen where the calendar was assumed to be Gregorian - this broke when I tried setting the culture to th (Thai) - they use the Buddhist calendar, which is ~543 years ahead. Its the year 2558 in that calendar - as you can imagine, not converting dates into UTC caused some problems...
Related
Just can't get it with datepicker validation.
I have datepicker From and datepicker To, so I want to prevent the user from doing some kung fu and seting datepicker From to be bigger than datepicker To, I've bumped across some questions but couldn't find the answer, so I've tried doing the easiest way I could think of:
Set MaxDate property for datepicker from in form_load event
private void Form1_Load(object sender, EventArgs e)
{
datepickerFrom.MaxDate = datepickerFrom.Value;
}
Then do the same for value_changed event
private void datepickerFrom_ValueChanged(object sender, EventArgs e)
{
datepickerFrom.MaxDate = datepickerFrom.Value;
}
This was easy and fine, only few lines of code, and I've only needed datepickerFrom_ValueChanged event, but recently I've tried typing date into datepicker insted of selecting it, and then all hell broke loose.
So I came to some solution for validation, instead of setting MaxDate property, I've tried this.
private void dtFrom_ValueChanged(object sender, EventArgs e)
{
DateTime from = datepickerFrom.Value;
DateTime to = datepickerTo.Value;
int year= from.Year > to.Year ? to.Year : from.Year;
int month = from.Month > to.Month ? to.Month : from.Month;
int day = from.Day > to.Day ? to.Day : from.Day;
int hour = from.Hour > to.Hour ? to.Hour : from.Hour;
int minute = from.Minute > to.Minute ? to.Minute : from.Minute;
int second = from.Second > to.Second ? to.Second : from.Second;
//setting datepicker value
datepickerFrom.Value = new DateTime(year, month, day, hour, minute, second);
}
This works fine, but feels like bit of headache, and I have to do this for datepickerTO_ValueChanged event also, sure I could make one method and call it two times, but still feels like there is a batter way for this, so any suggestions?
Thank you for your time
Solution 1:
You can handle datePickerTo close event and do something like:
private void dateTimePickerTo_CloseUp(object sender, EventArgs e)
{
DateTime fromdate = Convert.ToDateTime(dateTimePickerFrom.Value);
DateTime todate1 = Convert.ToDateTime(dateTimePickerTo.Value);
if (fromdate > todate1)
//Error
}
You can also use DateTime.Compare whcih get two date
like
int result = DateTime.Compar(dateTimePickerFrom.Value ,dateTimePickerTo.Value);
if result is 1 means From date is earlier, see this link.
Note1:
but as you said if user type in From or To textboxes then closeup event never fire so you need compare them in where you want to process
such as button click.
Note2:
As #Sinatr comment if Value is DateTime then don't need to convert it so the code would be like:
if (dateTimePickerFrom.Value >dateTimePickerTo.Value)
//Error
Your proposal would lead to a horrible interface. Suppose the following case:
From = 1 jan 2000
To = 1 feb 2000
User wants to change both values to 2010. He starts with the from value:
From = 1 jan 2010
Now he wants to change the TO value to 1 feb 2010. Alas, he can't.
Proper usage would be: add some button with which the operator can affirm he has changed all data, start checking it and update. In windows this button is usually named Apply Now or OK. Why deviate from this windows standard.
private void OnFormLoading(object sender, ...)
{
this.FromDate.MinValue = ... // use the real absolute min value you want ever to allow
this.FromDate.MaxValue = ...;
this.ToDate.MinValue = ...;
this.ToDate.MaxValue = ...;
}
Don't do any checking as long as the operator is making changes. Strat checking the input values when he indicates that he finished making changes:
private void OnButtonApplyNow_Clicked(object sender, ...)
{
bool InputOk = CheckInput();
if (!inputOk)
{
ShowIncorrectInput(); // for instance using a MessageBox
}
}
Good day fellow helpers, i have following problem:
(running MS Visual Community Edition 2015)
private void button4_Click(object sender, EventArgs e) // Senden
{
serialPort2.WriteLine("SR,00,002\r\n");
textBox1.Text = "gesendet";
textBox3.Text = "";
try
{
System.IO.StreamReader file = new System.IO.StreamReader("C:\\blub.txt");
String line = file.ReadToEnd();
string Hallo = line; \\in the beginning there is "0" in the file
file.Close();
decimal counter = Convert.ToDecimal(Hallo); \\just for testing
counter++;
string b = serialPort2.ReadLine();
string[] b1 = Regex.Split(b, "SR,00,002,"); \\cuts off unwanted input from device
decimal b2 = decimal.Parse(b1[1]); \\number like -3000
System.IO.StreamWriter test = new System.IO.StreamWriter("C:\\blub.txt");
test.WriteLine(counter);
test.Close();
textBox7.Text = "Das ist counter:" + counter;
}
catch (TimeoutException)
{
textBox3.Text = "Timeout";
throw;
}
}
Now, the Serialport is a device that returns a lengthmeasurment. As it is a bit weird, or just the way its build it start with a negitve number (between -5000 and -3370). Now as i want to get measurement on the screen that is realistic i want to set the value to 0 and calculate the difference.
Means: I start the programm - press send - get a value (say -3000) - press send again (after pushing the seonsor in) and get the value that its been pushed in > 0 by adding the difference to 0.
I only learned to store values externally when i had a C course a year back like i did within my programm. Is there a way to store the value from the first measurement in the programm so i can use it on the next send/try?
The counter was just for testing and I would exchange it for the "decimal b2"
I hope there is an easy fix for that, not really a pro with C# yet but i'm eager to learn. I thank the willing helpers in advance, MfG, Chris
OK, I will simplify this in order to show concept so it will not have all the code you are actually using.
So, what you want is to click on button, get some values and store them for next click.
Value is stored in variable. If you have variable in function that is handler for click event, as soon as function completes execution, value will be destroyed.
So, what you need is to create variable in outer scope (class level). Your function is already in class of the form so let's get to code:
class Form1
{
string BetweenClickStorage;
private void button4_Click(object sender, EventArgs e)
{
//Load data here
BetweenClickStorage = LoadedData;
}
}
After this, when you click again on the button, value will still be in BetweenClickStorage. It will be also available to all other buttons click handlers and other code in that form.
If I'm understanding your question correctly, the answer is simply to declare a variable outside the try/catch:
//declare variable //
var measurement;
// TRY #1 //
try
{
//assign value to the variable here
}
catch
{
}
// TRY #2 //
try
{
// reference variable here
}
catch
{
}
I have written a little program. It works almost as I want, I just have one problem. I am trying to copy all functions I have found in the other program.
I have a TextBox, when the user can write a phone number. Firstly, he is only allowed to use digits and "+"and "-", so I use:
private void textBoxPhoneNumber_KeyPress(object sender, KeyPressEventArgs e)
{
if ((char.IsDigit(e.KeyChar) == false) && (e.KeyChar != '+') && (e.KeyChar != '-') && (e.KeyChar != '\b')) e.Handled = true;
}
Then I want the phone number to be in certain format (+12-34-1234567), so I use:
private bool IsPhoneNumberCorrect(string name)
{
return Regex.IsMatch(name, #"^+\+[0-9]{2}-[0-9]{2}-[0-9]{7}$", RegexOptions.None);
}
and finally this (with TextChange):
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
checkIfOk();
textBoxPhoneNumber.Focus();
}
I use counter4 as a part of method (checkIfOk) that enables button. There is also an "X" icon that changes into "tick" when the number is given in proper format.
It works perfectly for me (just like in the program I am copying) - when the user writes something in the TextBox, he can only use digits and "+" and "-" and when the format is ok the icon changes and when other textboxes are also ok, the Ok buton enables.
Now, finally, the problem:
I am able to paste something from the Clipboard. In the original program, when I paste something with letters, digits and other signs, only digits and "+" and "-" remains. My program accepts everything in such situation.
I've been looking for something that might be helpful, but all I have found was very complicated. Is there a way to do it?
I tried to do something like this. It causes that when pasting only digits and "+" and "-" remains as it should, but the user can't write anything.
I am still a beginner. Maybe I am making a simple mistake?
private void phoneNumberValidity(object sender, EventArgs e)
{
Regex regex = new Regex("[^0-9-+]");
if (regex.IsMatch(Clipboard.GetText()))
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
checkIfOk();
textBoxPhoneNumber.Focus();
}
}
I am trying to do something like this:
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
checkIfOk();
textBoxPhoneNumber.Focus();
Regex regex = new Regex("[^0-9-+]");
if (textBoxPhoneNumber.Text.Contains("a"))
{
if (regex.IsMatch(Clipboard.GetText()))
{
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
}
}
}
I know that it's not exactly what I want, but maybe someone can give some clues...
Generally i thought, that I'd like to check if the text in tb contains some unwanted elements, but I don't know how to check it. As you can see, it checks only one unwanted element.
First of all, please use TRY-Catch for the Convert.ToInt32 !
Second: Use TextChanged event, and validate the input with the actual content of the TextBox
To validate, you can do something similar:
string output = ""
string clipboardText = GetClipboardText()
for each chara in clipboardText's characters
if chara.isNumeric or chara=='+' or chara == '-'
output += chara
end foreach
Of course its just a simple soultion, but you can confgure it as you want.
Or if you want more complex way, you can play with the regex... Start with number or + - BUT not contains alphabetical char. Based on your request.
This is what I made, and it works :) I will only add try-catch block as Krekkon has suggested.
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
if (Regex.IsMatch(textBoxPhoneNumber.Text, "[^0-9-+]"))
{
Regex regex = new Regex("[^0-9-+]");
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
}
checkIfOk();
textBoxPhoneNumber.Focus();
}
Maybe it will help someone in the future.
Maybe you should try like this: leave the first version of phoneNumberValidity method as it is and then check if the tb Text has some unwanted elements, get rid of them.
I have 2 datetime pickers and i want to display number of days between them on a text box if a user selects a date.. the problem with my code is that its not giving me correct answers and the time span doesnt seem to work.. i dont know where im going wrong thats why i asked for assistance.
I hope that explained better, please bear with me, its my first time to be on this site so im not familiar with the controls, sending stuff and updating
When i choose different dates it gives me answer 10.999998008713 days instead of 11 days and i dont know if i need to do math roundup
private void btnCalc_Click(object sender, EventArgs e)
{
DateTime start = ArrivalDate.Value;
DateTime finish = DepartureDate.Value;
TimeSpan numberOfNights = finish-start;
double TotalDays= numberOfNights.Days;
txtBoxNum.Text = (numberOfNights.ToString());
}
private void ArrivalDate_ValueChanged(object sender, EventArgs e)
{
DepartureDate.Value = ArrivalDate.Value.AddDays(1);
}
private void DepartureDate_ValueChanged(object sender, EventArgs e)
{
// setting messagebox to a sensible default message if no date or wrong date picked
if (DepartureDate.Value < ArrivalDate.Value)
{
MessageBox.Show("Cannot be less than previous date");
DepartureDate.Value = ArrivalDate.Value.AddDays(1);
}
else
{
double Days = (DepartureDate.Value - ArrivalDate.Value).TotalDays;
txtBoxNum.Text = Days.ToString();
return;
You need to get only the date part from your date picker:
DateTime start = ArrivalDate.Value.Date;
DateTime finish = DepartureDate.Value.Date;
Otherwise you also get time which interferes with your calculations.
Also, to display number of days as integer, use:
int TotalDays = numberOfNights.Days; // Days is int anyway
txtBoxNum.Text = TotalDays.ToString();
Or simply
txtBoxNum.Text = numberOfNights.Days.ToString();
You can actually put the whole code into one line:
txtBoxNum.Text = new TimeSpan(DepartureDate.Value.Date.Ticks - ArrivalDate.Value.Date.Ticks).Days.ToString();
I just want to know how to use the updated rate throughout the whole program. Here's my code so far for reference...
//Form 1
private void update_Click(object sender, EventArgs e)
{
if (fromcountry.Text == tocountry.Text)
{
MessageBox.Show(" Please Choose Two Different Currencies To Use This Function", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
btnconvert.Enabled = true;
Exchange_Rate frm = new Exchange_Rate();
frm.Show(this);
}
}
//Form 1 one of the comboboxes for selecting 2nd country
private void tocountry_SelectedIndexChanged(object sender, EventArgs e)
{
btnupdate.Enabled = true;
btnconvert.Enabled = true;
txtvalue.Enabled = true;
exchange();
}
private void exchange()
{
if (fromcountry.Text == tocountry.Text)
{
lblexchange.Text = "1";
}
else if (fromcountry.Text == "SGD - Singapore Dollar" && tocountry.Text == "USD - US Dollar")
{
lblexchange.Text = "1.26";
}
else if (fromcountry.Text == "SGD - Singapore Dollar" && tocountry.Text == "MYR - Malaysian Ringgit")
{
lblexchange.Text = "2.35";
}
else if (fromcountry.Text == "SGD - Singapore Dollar" && tocountry.Text == "EUR - Euro")
{
lblexchange.Text = "0.60";
}
//Form 2
private void btnok_Click(object sender, EventArgs e)
{
try
{
double exchange;
exchange = Double.Parse(txtcurrent.Text);
var frm = (currencyconverter)this.Owner;
frm.PassValue(txtcurrent.Text);
this.Close();
}
catch
{
MessageBox.Show("Please Enter Numbers", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtcurrent.Text = "";
}
}
I know by using if-else method it's too vague to get rates at the start of the program and I'm just a student learning simple programming. But still I need to know how use the updated rate when I press the same conversion again. If there's not enough info, I can help you get more coding
You can use a shared currency object to hold information about rate of the currency
public class Currency
{
private Currency(string name)
{
Name = name;
}
public string Name {get; private set;}
public decimal Rate {get; private set;}
private void SetRate(decimal rate)
{
Rate = rate;
OnRateChanged(this);
}
public static event EventHandler RateCanged;
private static OnRateChanged(Currency currency)
{
var handler = RateChanged;
if(handler != null)
{
handler(currency, EventArgs.Empty);
}
}
private Dictionary<string, Currency> currencies = new Dictionary<string, Currency>();
public static Currency GetCurrency(string name)
{
Currency currency;
if(!currencies.TryGetValue(name, out currency))
{
currency = new Currency(name);
currencies[name] = currency;
}
}
}
So you had a simple shared rate's storage, you can use it everywere
class Form1
{
public Form1()
{
...
Currency.RateChanged += RateChanged;
}
private void RateChanged(object source, EventArgs e)
{
labelRate.Text = Currency.GetCurrency("USD").Rate;
}
}
class Form2
{
public Form2()
{
...
rateTextBox.Text = Currency.GetCurrency("USD").Rate.ToString();
}
void updateButtin_Click()
{
Currency.GetCurrency("USD").SetRate(decimal.Parse(rateTextBox.Rate));
}
}
There are a number of different ways to achieve this and it's going to be impossible to answer in full without making a design decision for you. The approaches which spring to mind are either using a configuration file, database or some external source.
As you've pointed out you need to have some way of storing these values outside your application so if an conversion rate changes you can update it in your software without rewriting your code.
You need to make a decision on how to do this.
Database
A database is probably the most flexible, however it will require you to maintain it. There are countless mechanisms to access a database from ADO.NET, through Linq2SQL or NHibernate.
External Source
I'm sure there are various online sources you could get currency data from, either a webservice or RSS feed you could access - it could be worth reading up on these?
Configuration
Personally this is the approach I'd suggest. As you're clearly not very experienced I'd suggest the easier solution of config, work on your database skills - in the future it will be a no brainer for you.
I would use the AppSettings section of the config file similar to here.
You would add an App.Config file to your application, this would store the conversion rates so you can update them without needing to rewrite your tool. You can create a new file by right clicking on the project and adding New Item, then Configuration File.
You'll also need to add a reference onto System.Configuration as it's not referenced by default.
There is a section in the config file called AppSettings, this is a simple section for key/value type properties. We're going to create a set of app settings, one for each conversion rate. For example:
You can then use your countries to generate this key. For Example:
string settingKey = string.Concat(fromcountry.Text, "_", tocountry.Text);
You can access this configuration value using the ConfigurationManager:
decimal rate = decimal.Parse(ConfigurationManager.AppSettings[settingKey]);
Once you've got the rate you'll be able to perform your multiplication to calculate the correct values.
Please bear in mind there's no error handling in here - what happens if there country is not known or the config doesn't contain the exchange rate!
If you are not using actual currency data and just a static data, then here are the steps to improve:
Have one currency as base currency. Usually it's USD with value 1
Store all the rates for all the currencies in a collection [Key,Value] in USD.
Here the Key is your Currency Code eg, SGD and value is its rate in USD.
Now you can pass the selected dropdown value as Key to retrieve the value eg, Currencies[toCountry.Code]
Now to get the rate. You can divide like this to get value of FromCountry in terms of ToCountry
var FromCountryRate = Currencies[FromCountry.Value]/Currencies[ToCountry.Value];