Sumel007
Topic Author
Posts: 30
Joined: 19 Mar 2020, 10:50

Bindings to ScaleX and ScaleY do not get updated

25 Jan 2022, 12:18

I have a button control template and I want to animate the background scale without animating any contents of the button.
I have created two grids one inside the other, with the outer grid having the background and the inner grid being transparent. I use a storyboard to change scale of the outer grid and I want to use binding with a Converter to rescale the inner grid to the inverse of the outer grid. This works in WPF, but does not seem to work in Noesis.

The grids:
<Grid x:Name="scalingGrid" Background="{TemplateBinding Background}" RenderTransformOrigin="0.5,0.5">
                            <Grid.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform x:Name="scalingGridScale" ScaleX="1.0" ScaleY="1.0"/>
                                    <SkewTransform/>
                                    <RotateTransform/>
                                    <TranslateTransform/>
                                </TransformGroup>
                            </Grid.RenderTransform>
                            <Grid x:Name="reverseScalingGrid" RenderTransformOrigin="0.5,0.5">
                                <Grid.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform ScaleX="{Binding ScaleX, ElementName=scalingGridScale, Converter={StaticResource multiplicativeInverseFloatConverter}, UpdateSourceTrigger=PropertyChanged}" 
                                                        ScaleY="{Binding ScaleY, ElementName=scalingGridScale, Converter={StaticResource multiplicativeInverseFloatConverter}}"/>
                                        <SkewTransform/>
                                        <RotateTransform/>
                                        <TranslateTransform/>
                                    </TransformGroup>
                                </Grid.RenderTransform>
The converter:
public class MultiplicativeInverseFloatConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
#if NOESIS
            float var = (float)value;
            
#else
            double var = (double)value;
#endif
            System.Console.WriteLine(var.ToString());
            return 1/var;

        }
The animation:
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="scalingGrid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                                        <EasingDoubleKeyFrame KeyTime="{StaticResource UCTransitionTime}" Value="1.33"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="scalingGrid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                                        <EasingDoubleKeyFrame KeyTime="{StaticResource UCTransitionTime}" Value="1.33"/>
                                    </DoubleAnimationUsingKeyFrames>
The convert function only gets called twice (once for scaleX, once for scaleY), but does not get called when the storyboard is played.


EDIT:
I tried to work around this by binding the whole ScaleTransform and using a converter to convert the Scale (instead of ScaleX and Y individually). It also doesn't work in Noesis.
public class ReverseScaleTransformConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            ScaleTransform trans = (ScaleTransform)value;
            Console.WriteLine(trans.ScaleY.ToString());
#if NOESIS
            return new ScaleTransform(1.0f / trans.ScaleX, 1.0f / trans.ScaleY);
#else
            return new ScaleTransform(1.0 / trans.ScaleX, 1.0 / trans.ScaleY);

#endif
        }
<Grid x:Name="scalingGrid" Background="{TemplateBinding Background}" RenderTransformOrigin="0.5,0.5">
                            <Grid.RenderTransform>
                                <ScaleTransform x:Name="scalingGridScale" ScaleX="1.0" ScaleY="1.0"/>
                            </Grid.RenderTransform>
                            <Grid x:Name="reverseScalingGrid" RenderTransformOrigin="0.5,0.5" RenderTransform="{Binding RenderTransform, ElementName=scalingGrid, Converter={StaticResource reverseScaleTransformConverter}, UpdateSourceTrigger=PropertyChanged}" >
                             
What's interesting is that in WPF the Console.WriteLine gets called once at the beginning and then gets called multiple times when the storyboard plays (as expected). In Noesis however it gets called 3 times at the beginning (and doesn't get called during the storyboard). I suspect the triple call is related to me having three states in the VisualStateManager that work on the scale.
 
User avatar
sfernandez
Site Admin
Posts: 2997
Joined: 22 Dec 2011, 19:20

Re: Bindings to ScaleX and ScaleY do not get updated

26 Jan 2022, 17:30

Which version of Noesis are you using? Because we had a bug (#1476) in versions prior to 3.1.2 where named freezables inside a template are not correctly resolved by bindings.

If you can't upgrade your version you can workaround it by changing the ElementName in the binding to use the FrameworkElement containing the ScaleTransform:
<ScaleTransform
  ScaleX="{Binding RenderTransform.Children[0].ScaleX, ElementName=scalingGrid, Converter={StaticResource multiplicativeInverseFloatConverter}}" 
  ScaleY="{Binding RenderTransform.Children[0].ScaleY, ElementName=scalingGrid, Converter={StaticResource multiplicativeInverseFloatConverter}}"/>
 
Sumel007
Topic Author
Posts: 30
Joined: 19 Mar 2020, 10:50

Re: Bindings to ScaleX and ScaleY do not get updated

28 Jan 2022, 13:09

We were indeed using version 3.1.1, sorry for not specifying it in OP. Updating to 3.1.2 resolved the issue for the first binding (where we bind scaleX and scaleY).
The binding from my edit where we bind the whole scale transform still doesn't seem to work though (even though it works in WPF). This is not an issue for me, since I'll just use ScaleX and ScaleY bindings individually, but I thought I'd let you know.

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 45 guests