Search code examples
wpfxamlbindingcode-behind

WPF binding in codebehind fails for transformations


Displaying a rectangle and binding Width, Height, Angle to a view model class works as I expect in XAML

<Rectangle 
  RenderTransformOrigin="0.5,0.5" 
  Fill="Black" 
  Width="{Binding Path=Width, Mode=TwoWay}" 
  Height="{Binding Path=Height, Mode=TwoWay}">
  <Rectangle.RenderTransform>
    <RotateTransform Angle="{Binding Path=Angle, Mode=TwoWay}" />
  </Rectangle.RenderTransform>
</Rectangle>

However, when creating a rectangle in the code-behind I can bind to the Height and Width, but not the Angle.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
  Binding bindH = new Binding("Height");
  bindH.Mode = BindingMode.TwoWay;

  Binding bindW = new Binding("Width");
  bindW.Mode = BindingMode.TwoWay;

  // DOES NOT WORK
  // AND I DID TRY MANY OTHER COMBINATIONS
  Binding bindA = new Binding("Angle");
  bindA.Mode = BindingMode.TwoWay;

  Rectangle r1 = new Rectangle();
  SolidColorBrush myBrush = new SolidColorBrush(Colors.Black);
  r1.Fill = myBrush;
  r1.RenderTransformOrigin = new Point(0.5,0.5);
  r1.SetBinding(Rectangle.WidthProperty, bindW);
  r1.SetBinding(Rectangle.HeightProperty, bindH);

** // Does not work**

  r1.SetBinding(RenderTransformProperty, bindA);

  LayoutPanel.Children.Add(r1);                     // my custom layout panel
}

All help appreciated.


Solution

  • Your Angle property in the ViewModel must be exposed as a RotateTransform. A trivial implementation of the VM would look like this:

    public class ViewModel
    {
        public RotateTransform Angle { get; set; }
        public int Height { get; set; }
        public int Width { get; set; }
    
        public ViewModel()
        {
            Angle = new RotateTransform(10);
            Height = 50;
            Width = 100;
        }
    }
    

    The binding then works exactly as you have written it in the Window_Loaded event handler. This makes sense, because in the working XAML version, you specify a RotateTransform object declaratively within the Rectangle's RenderTransform tags.

    Hope this helps :)