I know there are many times that it would be nice to give the user the ability to enter an equation in a TextBox instead of letting the user calculate the value before entering it. I have worked on projects that have implemented this functionality.
Eval() function. As I was working on this, I suddenly realized that I could actually do things in the opposite way, and get a value converter that would evaluate a string to return a calculated value to the binding element. It actually ended up working better than I thought.
public function Evaluate(expr : String) : String
return eval(expr, "unsafe");
The value converter is actually very simple since only the
ConvertBack method has any significant code, and it has very little:
class EvaluationValueConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter,
public object ConvertBack(object value, Type targetType, object parameter,
if (value == null)
catch (Exception e)
Since there is no processing on the value from the ViewModel, the
Convert method just returns the value argument.
Eval() method through the
Evaluate method of an instance of the
TextBox automatically handles the problem with the null value being passed to the ViewModel; where the property is of type decimal or some other non-nullable type, it changes the
TextBox border to red. What is nice is that the equation in the
TextBox can still be edited to correct errors.
Obviously this is not ideal because the value of the property in the ViewModel does not correspond to what is displayed, and the ViewModel does not know that there is an issue with the user entry.
Calculation Engine Options
Eval() function will process these, but they are case sensitive, and must be preceded by “
Math.”. Another disadvantage is that it does not support the exponent operator (“^”)--instead the
pow function must be used. Ideally, a better evaluator can be created, and there are a number of good ones that can be found on the internet, but I wanted to avoid tramping on toes. The
Eval() function is very powerful, and can do a lot more than anybody will probably want. A little bit of work could fix the problems with the
pow function and case sensitivity.
I found a number of other options on the internet:
All are good options, several would be better than mine since it would be more intuitive for the user.
The Example in Use
Here a user has entered an equation, but has not left the TextBox, therefore the value converter has not processed the equation to determine if it is invalid:
After leaving the TextBox, the value converter has determined that there is an error in the user input, and returned a null to the property, causing an error to be identified by the View:
Here the user is entering an equation with a transcendental function (this is before the focus leaves the TextBox):
After the focus leaves the TextBox, the following is displayed:
Fixing User Input Error Detection
Eval() method), which will be the type of string.
The last solution is the one I think is best. If an indication is needed on the form for an error, then a value converter could be used for some attribute (border, background, etc.) that would set the property to the invalid value if the property is non-numeric. The ViewModel would know that the property is invalid because it is non-numeric. The only thing left would be to convert the property between a string value and the proper numeric value for the Model. This is a little more work, but not bad for the functionality added.
What I would say is that this is a case that Microsoft missed an obvious feature in WPF; there is obviously an error, but no way to pass this information to the ViewModel.
Right now the value converter is not very smart, and if this converter is bound to a whole number type (e.g.,
Integer) format, and the
Eval() method returns a floating or fixed point value, it will cause an error. This can easily be fixed by adding code that determines the type of the property being bound to, and does the conversion before returning the value. This will also be a problem for overflow.
This value converter makes it very quick and easy to add the ability for the user to input equations in text boxes that are bound to numeric properties. It has a problem in that if the user inputs an invalid equation, the ViewModel will not know that there is a problem, and so it is possible to continue with an invalid equation in the text box. It this is acceptable, then this is a great option.
Eval() method to evaluate a string, and this can be used in other ways that may be more appropriate for the application.