Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF why is my ScaleTransform Frozen and how can I bind to it?

I have a pretty simple user control that I want to bind a ScaleTransform property to a DP in the code behind like so:

<UserControl 
x:Name="RoundByRound"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
...
>

<Canvas x:Name="MyCanvas">
  <Canvas.RenderTransform>
    <TransformGroup>
      <ScaleTransform ScaleX="{Binding ZoomTransform.ScaleX, ElementName=RoundByRound}" 
                      ScaleY="{Binding ZoomTransform.ScaleY, ElementName=RoundByRound}"/>
      <SkewTransform/>
      <RotateTransform/>
      <TranslateTransform X="{Binding TranslateTransform.X, ElementName=RoundByRound}" 
                          Y="{Binding TranslateTransform.Y, ElementName=RoundByRound}"/>
     </TransformGroup>
   </Canvas.RenderTransform>
</Canvas>
</UserControl>

and then in the code behind I do this:

ZoomTransform.ScaleX = 3;
ZoomTransform.ScaleY = 3;

But I got an error saying:

Cannot set a property on object '...' because it is in a read-only state.

So I changed it to:

var cloned = ZoomTransform.Clone();
cloned.ScaleX = 3;
cloned.ScaleY = 3;
ZoomTransform = cloned;

But now that actually does nothing... no scale gets applied to my canvas.

HOWEVER

If I remove the binding on the ScaleTransform and just have it as an empty XAML element:

<ScaleTransform />

Then in my code I do this:

(MyCanvas.RenderTransform as TransformGroup).Children[0] = new ScaleTransform(3, 3);

It works! I get the scale applied

So 2 questions:

  1. Why is my Transform Frozen is the first place?
  2. Why doesnt my binding work when I clone the transform?

Thanks all!

UPDATE:

Here is the definition of the DP:

public static readonly DependencyProperty TranslateTransformProperty = DependencyProperty.Register("TranslateTransform",
            typeof(TranslateTransform),
            typeof(RoundByRoundControl),
            new PropertyMetadata(new TranslateTransform { X = 0, Y = 0 }));

        public static readonly DependencyProperty ZoomTransformProperty = DependencyProperty.Register("ZoomTransform",
            typeof(ScaleTransform),
            typeof(RoundByRoundControl),
            new PropertyMetadata(new ScaleTransform { ScaleX = 1, ScaleY = 1 }));

        public TranslateTransform TranslateTransform
        {
            get { return (TranslateTransform)GetValue(TranslateTransformProperty); }
            set { SetValue(TranslateTransformProperty, value); }
        }

        public ScaleTransform ZoomTransform
        {
            get { return (ScaleTransform)GetValue(ZoomTransformProperty); }
            set { SetValue(ZoomTransformProperty, value); }
        }
like image 763
Mark Avatar asked Nov 06 '22 16:11

Mark


1 Answers

The ScaleTransform that you pass as your default value for your ZoomTransform property is frozen by the PropertyMetadata. Once the PropertyMetadata is passed to the Register method is will be frozen/sealed.

However, once the metadata is consumed as part of a call to Register, AddOwner, or OverrideMetadata, the property system will seal that metadata instance and the properties are now considered immutable. Attempting to set DefaultValue once IsSealed is true on this metadata instance will raise an exception.

Since the ScaleTransform is a Freezable, it is frozen as part of this process.

As for you second question, based on the code you provided it does correctly apply the ScaleTransform when cloning the ZoomTransform. There must be something else going on that you haven't included.

This is assuming that the XAML for your UserControl includes an x:Class attribute which ties to the code-behind file for RoundByRoundControl.

like image 184
CodeNaked Avatar answered Nov 17 '22 00:11

CodeNaked