16

Can I have the following (the ActualWidth divided by 2)?

<StackPanel Name="SP2" Width="{Binding ElementName=SP1, Path=ActualWidth/2}">

Doesn't seem to work for me.

Thanks.

Alberto
  • 35
  • 3
Old Geezer
  • 14,854
  • 31
  • 111
  • 198
  • What are you trying to do? Get `Width` set to half the value of `SP1.ActualWidth`? If so, a `Converter` is probably what you're after. – Philip Kendall Jun 29 '12 at 05:48
  • Please don't use `ActualWidth` in bindings, as it's not a dependency property and won't necessarily do what you expect. See questions http://stackoverflow.com/questions/7403151 (WPF) and http://stackoverflow.com/questions/1602148 (Silverlight). – Luke Woodward Jun 30 '12 at 21:00
  • @PhilipKendall, yes that was what I was trying to do. I want SP2 to be half the width of SP1 every time the window is resized. – Old Geezer Jul 02 '12 at 00:55
  • Place the two stack panels inside a two column grid, with column widths "2* and "*" respectively – Peregrine Jul 02 '12 at 10:34

2 Answers2

23

You can use a custom converter to perform simple calculations directly in XAML.

Take a look, for example, at this implementation:

MathConverter

Simple usage:

<RotateTransform Angle="{Binding Text, ElementName=Seconds,
    Converter={ikriv:MathConverter}, ConverterParameter=x*6}" />

The classical approach is to create a readonly calculated property. So in this simple case you can add a second property HalfWidth.

public double HalfWidth
{
    get
    {
        return ActualWidth / 2.0;
    }
}

The bad news is that when ActualWidth is updated, the StackPanel on the view bound to HalfWidth will not update. This is because the view does not know that HalfWidth has changed.

By raising a property changed event on HalfWidth in the setter of ActualWidth, the view will query HalfWidth and hence retrieve the correct value.

private double _actualWidth;
public double ActualWidth
{
    get
    {
        return _actualWidth;
    }
    set
    {
        if (_actualWidth != value)
        {
            _actualWidth = value;
            OnPropertyChanged("ActualWidth");
            OnPropertyChanged("HalfWidth");
        }
    }
}

The main proplem about this approach is that it will soon become a nightmare when we have numerous calculated properties with no setters.

That's why (in a MVVM pattern) I personally prefer to use a custom converter.

Paolo Moretti
  • 54,162
  • 23
  • 101
  • 92
  • Thanks. How would one decide whether to go through all this effort or to just have one line in the Windows's SizeChanged event handler in code behind? – Old Geezer Jul 02 '12 at 03:10
2

No, you can only use properties (and indexes into arrays/collections in some cases) in bindings.

Instead you need to either bind to a notify property that returns the intended value (e.g. ActualWidth/2), or use a converter that returns a value with your calculation applied.

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202