In my WPF application the user is inputting a GPS coordinates in the format of Degrees : Minutes : Seconds as decimal fraction of minutes.
So 60° 30' 45" would be entered as 60° 30.750' .
I then store it as a pure decimal number so the above example would be stored as 60.5125.
The idea was that so the users wouldn't mess up the input it would be set in 3 different textboxes. One for Degrees, other for Minutes and one for the fractionalSeconds. It's somewhat bad that one of the numbers is seperated into two textboxes but if they have to type the whole number in the are afraid of all the point or comma confusion and that they could mess up.
So one thing I thought might work was a IMultiValueConverter but it seems to only work with MultiBindings which is something I'm not doing here.
Currently my solution is to bind to different properties and do all the calculations in code behind but I'm not really happy about the fractional bit. I assume 3 fractional letters but if they enter only 7 and assume 0.700 but get 0.007 so I thought I would have to do a string format bit.
Is there a better solution out there. Can I use MultiValueConverter for something like this?
You could try using a MaskedTextBox, such as the one from the Extended WPF Toolkit.
You could use a Masked TextBox. This implementation uses MaskedTextProvider which is a .net class.
Related
I'm currently working on a form with a bunch of textboxes with quite specific requirements. For example one textbox contain cadastral number and should look like ##:##:#######:~ (last range of digits varies) and also it would be quite nice to see the pattern before you even type anything (if I recall correctly it's called mask). Also giving requirements first two digits always should be 24, so the end result should look shomething like this 24:##:#######:~. Another example is a numeric textbox with units and spaces between big digit numbers (ex 1 000 000 m2). For short this one text box and the others have both static elements (which user should not be able to edit) and dynamic (which makes masked textboxes and similar stuff quite hard to deal with).
So, I've tried different things:
Using maskedTextBox from toolkit package, which turned out bad, because it did poorly handle last part with range of digits, and also when a key was pressed when in the middle of the static mask, it just pushed the carret, but not actually add anything to the text;
Using converters prove quite chalenging at first, but gave remarcable results, it handles variable range of part perfectly, partialy, because of custom converter, but it was difficult to manage things, when user deleted text, because of static parts being integrated in the converter itself;
Using StingFormat for textbox with binding text property was almost useless, although it handle static part quite well, and in the end I couldn't make it work.
Intuition tells me a combination of a custom converter (handling dynamic part) and and StringFormat (handling uneditable static part) should do the job. Maybe the number of requirements is just too much for a simple textbox. Also one thing is bugging me, there could be a sutable existing general solution, that I am not aware of (At first I didn't know Converters was a thing).
Now the question, how would you generally approach this problem? Is there any existing solutions, that with a bit of tweaking would work?
I have a GUI working on the front end. But on the back end I have a little problem with my math. Code is trying to calculate how much time has gone with only starting and ending hours. (There are no info on days). So I think I found the way to calculate the hours spent on paper. But in C# I failed I think because of local variable stuff.
float start = float.Parse(textBox1.Text);
float end = float.Parse(textBox2.Text);
float hours_spent = end - start;
if (start > end) {
hours_spent = 24.00f -start + end;
}
First part is working correctly but when I give the start bigger than end, it gives me random numbers.
EDIT: When i gave 14.00 as an input and 13.00 as an output i get -76
and for input 14.00 output 12.00 i get -176 and for 18.50 to 10.25 i get -801. It is not random i can see that too my bad on choosing the words. But i dont get it what is wrong
When i gave 14.00 as an input and 13.00 as an output i get -76
You are parsing in a part of the world where . is not the decimal separator but is a common "group" separator. That is, a number like one hundred thousand plus a quarter is written 100.000,25, and not as it would be in the United States, 100,000.25. Parse assumes that the string is in the format of the current user's locale unless you tell it otherwise.
Therefore you are parsing the strings into values 1400 and 1300. Their difference is -100, which is less than 0, so you add 24 to -100 and get -76.
Same for your other case. You have 1850 and to 1025, subtract them to get -825, add 24 and you get -801.
There's nothing "random" at all here; everything is working as expected.
There is a lesson here: work backwards. You got -76. How'd that happen? You must have added 24 to something. What added to 24 gives you -76? -100. How did we get -100? And so on.
Start over. You should not be parsing floats in the first place. If this is a decimal quantity then you should be parsing a decimal, and if you know that it will always have . as the decimal separator, you should say so when you parse it. (Hint: use the version of TryParse that takes a NumberStyles and set the style correctly.)
If, on the other hand, you know that this is two integers separated by a period, then you should not be parsing it as a decimal or a float. You should be parsing an integer, then a period, then an integer.
If this is hours then a period then minutes, then again, you should not be using any of the above. Use a date and time parser to parse dates and times.
In short: use the right tool for the job you actually have to do.
Other problems with your code:
Use TryParse, not Parse, when dealing with user input. You don't know that there is a valid number in there, but Parse will crash if it gets bad input.
Your math is probably wrong. If someone puts in 100 and 200, do you really want -76 as the output?
Take a step back and ask yourself what the real business process is that you're trying to build here. Write that business process down carefully and then implement that process, not an approximation of it. Your business process probably does not say "parse a float using the rules of the current locale" but that's the code you wrote. Write code that means exactly what you intend it to mean.
UPDATE: Comments on the question indicate just how deep a hole you've gotten yourself into:
If entry time is 13.55 and exit time is 14.05 what should be the expected logical result ? It should be 10 (minutes) or 50 (numeric difference) ?
I am expecting 10 as minutes
Then absolutely you should not be parsing as float or decimal! Parsing as float or decimal is obviously completely wrong because 1.1 and 1.10 are the same value as a number, but nine minutes different if it is "hours.minutes", and you can't tell which case you are in by parsing as a number.
Again, you need to stop writing code, erase everything you've written so far, and start over. You're in a hole: stop digging deeper, fill in the hole, and get back to ground level.
You need to figure out exactly what format your strings are in, and parse exactly that format and nothing else.
So, write a specification that poses and then answers questions about what is allowed and what is not. Are negative values allowed? What if the number of minutes is more than 60? What if the minutes or hours are missing entirely? And so on.
Once you have a specification, write test cases that verify the spec. Then write an implementation, and run your tests. The code is more likely to be correct if you write the tests first.
I'm going to completely ignore providing a didactic answer in favor of trying to sidestep the problem.
Avoid writing your own parsing code. Instead, replace all your TextBoxes with DateTimePickers with Format set to Time. Then pull out the time by calling the .Value.TimeOfDay property. TimeOfDay is a TimeSpan, so it supports simple arithmetic.
Warning: Watch out when pulling these results using the provided properties. For example, 150 minutes can be translated as either 2 .Hours and 30 .Minutes or to 150 .TotalMinutes .
For starters I'm very very new to writing code! :)
What I have so far...
So far I've used Xamarin.Forms to create a user interface for a sort of specialized calculator. I'm using a Grid Layout containing: a first column of Labels, a second column of Entries (that I have named in Xaml), and a third column of Steppers (so I can change the entries by typing or using the stepper). These 3 views on each row repeat for several rows with different label text on each row and at the bottom of the Grid Layout I have an Entry for the output.
The problem...
Basically, I want to buy a certain product at different weights and prices...among other criteria....and I want to quickly figure out how much money I'll make at a future possible sale price. Simply put... I'm trying to add/subtract/multiply/divide using Xamarin.Forms Entries. I've looked everywhere and can't seem find anyone giving an example of how to do this. I've tried different methods and usually end with an error of not being able to convert the Xamarin.Forms entry to a string...So I'm back to zero. Can I get an example of a Method where I would be able to add/subtract/multiply/divide 2 Xamarin.Forms Entry views together in the C# code behind? This seems very simple to me...what am I missing??? Is there a thread/article/video somewhere that I haven't found that covers this?? And like I said, I'm very new so the answer is probably very simple.
Thanks in advance!
Steven
Entries deal with strings, not numeric values, so you need to convert them before doing calculations.
var amount = Decimal.Parse(EntryA.Text);
var price = Decimal.Parse(EntryB.Text);
var total = amount * price;
// you can use a format string as an argument to ToString()
// to control the output - ie, how many decimals, commas, etc
LabelTotal.Text = total.ToString();
In a real app you will want to validate the input in case the user enters text instead of a value number (the Parse method will throw an exception if the input is bad);
My main problem is that i need to be able to have asp.mvc accept the Danish number format (meaning a dot every thousand and a comma seperator). Since i am working on a larger system, I need a more in-depth solution.
The formating problem includes the fact that I need to beable to solve the errorhandling aswell, which does not accept the 0,00 as a number. best case, the solution still maintains the possibility to calculate with the numbers without having to format them each time.
As another point, I need to beable to switch between the English format, meaning (0.00) and the Danish (0,00).
TL;DR
Solve the problem of using a diffrent formatting in mvc asp.net from (en 0.00) to (da 0,00), including errorhandling, still allowing for calculations in jquery or javascript, and the posibility to switch back to the english format (0.00).
What would be the best way to go about this?
Edit: Solved most of it!
To get the View (Jquery validate) to accept comma as a seperator I've inserted "One regexp" from this: http://mfranc.com/javascript/jquery-valdiator-modyfing-decimal-separator/
Adding the custom model binding, provided by #chrispratt solved the problem of the controller receiving the number in the right format.
On top of this I've added code to modify any number entered into an input field into the right format.
Also all numbers and their display formats are checked before being shown. (since some doubles display without ,00)
I think that should be it, now all that remains is to devise some method of switching between languages and formats, which I should beable to manage.
Thanks for the help!
Any help is apprichiated!
Thanks in advance!
I'm currently using the charting within .NET using System.Windows.Forms.DataVisualization.Charting.Chart. Thus far it seems very powerful, and works great. However, there is a huge problem in terms of how it is auto-calculating intervals. I use a lot of double values, and in libraries like ZedGraph, it handles this perfectly. It selects min/max/interval just fine. However, in MS Chart, it may select 206.3334539832 as a minimum, and intervals of a similar decimal precision. Obviously this looks quite ugly.
So, I tried simply making the axis format {0.00} and it works great when it loads the chart. Except when you zoom in, you need greater precision, maybe at 4 decimal places instead of 2. It seems I'm either stuck with 9 decimal places all the time, or else a constant fixed number that may break when someone requires greater precision. I'd rather it pick up the precision based on the level of zoom currently applied. Libraries like ZedGraph and Dundas (which I believe MS is even using!) tend to pick good values that change as you zoom in and out.
Is there any way to have the intervals change precision as the zoom frame changes? It's probably some simple property I have set wrong, but it's hard to tell with the millions of properties this thing has (especially when there's about 14 places that represent the concept of Interval).
I had the exact same problem when zooming. I added code to format the axis labels and call it from the Paint handler. The Axis View objects have an IsZoomed property and have functions to get the current axis limits (GetViewMinimum/Maximum). I set the Axis LabelStyle.Format to "N" for all cases unless the Max-Min=range is less than 1. Then I set the format to "F#" where # is calculated based on the axis range.
# = Convert.ToInt32(Math.Abs(Math.Log10(range) - .5)) + 1;
Having played around with the chart control I haven't been able to find a simple solution to your problem. However the following may help:
Have you considered setting the maximum and minimum values for the axes yourself? If you round the actual maximum and minimum values to the nearest sensible "round" number (5, 10, 0.5, 0.01) this should make the calculated intervals a bit more friendly.
I understand this is not an ideal solution but by carefully choosing the maximum and/or minimum values you can ensure the intervals are "nicer" numbers. If the range of your axes is say divisible by 2, 5 & 10 it should result in fairly nice intervals.
Why not modify number format string.
Create format string
string formatString = "{0.00";
Identify zoom level, say zoomLevel = 2;
formatString = formatString.PadRight(5+zoomLevel, '0');
formatString += "}";
Now use this format on axis legend. Use string builder or some better way to modify the format string.
To provide the result with minimal cost you can use exponential scientific format
You can attach to customize event.
From there, you can modify the labels on x-axis:
var xAxisLabels = chart1.ChartAreas[0].AxisX.CustomLabels;
...
xAxisLabels[0].Text = ...
set min. and max. values:
chart1.ChartAreas[0].AxisX.Maximum = ...;
etc.
you can dynamically update the max and min based on your data set. each time user zooms in, you do a FOREACH on every point and get the stats and based on that set your max and min
It helps to set the IntervalOffset of the axis, here an example:
Private Sub chMap_AxisViewChanged(sender As System.Object, e As System.Windows.Forms.DataVisualization.Charting.ViewEventArgs) Handles chMap.AxisViewChanged
'the grid ticks are rounded values
e.Axis.IntervalOffset = -e.Axis.ScaleView.ViewMinimum
End Sub