Binding to element in WPF: can the Path expression do math?

21,579

Solution 1

No it can't you should use binding converters

public class MyConverter : IValueConverter
{
public object Convert(object value, Type  targetType,
      object parameter, CultureInfo culture)
  {
      return (int)value/2;
  }

  public object ConvertBack(object value, Type targetType,
      object parameter, CultureInfo culture)
  {
    return null;
  }
}

Solution 2

I use a MathConverter to do math in my XAML bindings.The converter code can be found here and it is used like this:

Height="{Binding ElementName=RootWindow, Path=ActualHeight,
                 Converter={StaticResource MathConverter},
                 ConverterParameter=@VALUE/2}"

It will also handle more advanced math equations like

Height="{Binding ElementName=RootWindow, Path=ActualHeight,
                Converter={StaticResource MathConverter},
                ConverterParameter=((@VALUE-200)*.3)}"

Solution 3

No, standart binding doesn't support expressions in Path. But you can look at my project CalcBinding, which was developed specially to resolve this problem and some others. Say, you can write something like:

<Button Content="{c:Binding ElementName=grid, Path=ActualWidth+Height}"/>

or

<Label Content="{c:Binding A+B+C }" />

or

<Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />

where A, B, C, IsChecked - properties of viewModel and it will work properly

Goodluck!

Solution 4

@Rachel's MathConverter worked great for me, however I switched out the expression parsing and just left that bit to NCalc. That way I didn't have to worry about operator precedence.

using NCalc;

using System;
using System.Globalization;
using System.Windows.Data;

namespace MyProject.Utilities.Converters
{
    public class MathConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo     culture)
        {
            // Parse value into equation and remove spaces
            string expressionString = parameter as string;
            expressionString = expressionString.Replace(" ", "");
            expressionString = expressionString.Replace("@VALUE", value.ToString());

            return new Expression(expressionString).Evaluate();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Solution 5

Take a look at my MathConverter project. It allows for very advanced expressions, including string formatting.

In particular, your expression would be handled as such:

Height="{Binding ActualHeight, ConverterParameter=x/2, Converter={StaticResource math}}"

There are loads of examples, as well as a basic introduction of how to use it on the project's homepage.

Share:
21,579
John
Author by

John

Updated on July 18, 2022

Comments

  • John
    John almost 2 years

    I'm trying to bind a control to the parent's Height/width property using ElementName and a Path. However, I don't want to bind to the actual height, but to exactly half the height. Can the Path expression do the math?

    e.g. Path={ActualHeight/2}

    I couldn't find a way to do that. IS there any other clever approach?

    Thanks!

  • Gishu
    Gishu about 14 years
    Value converters exist solely for this purpose - to transform the value between the source and target - wpftutorial.net/ValueConverters.html. Or if that is too much, you could declare a new get-only property HalfOfActualHeight if that is an option.
  • John
    John about 14 years
    It seems this is exactly what I need, even if the task is so trivial. Thanks!
  • watbywbarif
    watbywbarif over 9 years
    Cool! Tried this, works without problem, code is more readable and shorter, no stupid converters lying around in files!
  • Nicholas Miller
    Nicholas Miller over 8 years
    By the way, when using NCalc, every expression is cached internally. Since this entails working with dynamic data-bound values, I'd suggest throwing EvaluateOptions.NoCache as the second parameter to the Expression constructor. That way you aren't consuming so much memory.
  • Matt Becker
    Matt Becker over 8 years
    It might improve memory consumption since the parsed logical expression isn't kept in each Expression object, but I think the performance would take a hit. Each time Evaluate() is called, you need to compile the expression from the original string. There's no documentation on the site (ncalc.codeplex.com), I'm just going from what I see in the code. (ncalc.codeplex.com/SourceControl/latest#Evaluant.Calculator‌​/…)
  • Nicholas Miller
    Nicholas Miller over 8 years
    Certainly it could drain performance. The benefit of caching is only applicable if the expression is being frequently reused. In my case, I bound to a double property which was generating a new expression each time I changed the value, and seldom reusing previous expressions. It's a time-space trade-off and depends on the application.
  • VivekDev
    VivekDev about 8 years
    You need to add a namespace prefix xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding". See the example github.com/Alex141/CalcBinding/blob/master/WpfExample/…