tags:

views:

1040

answers:

2

Hello,

I would like to bind a scaleTransform to a converter passing the ActualWidth or ActualHeight.

Here what I want to do :

<Canvas x:Name="Canevas">
        <Canvas.RenderTransform>
            <TransformGroup>
               <ScaleTransform ScaleX="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UIElement}}, Path=ActualWidth, Mode=OneWay, Converter={StaticResource ScaleConverter}, ConverterParameter={Binding Path=ActualWidth}"
                               ScaleY="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UIElement}}, Path=ActualHeight, Mode=OneWay, Converter={StaticResource ScaleConverter}, ConverterParameter={Binding Path=ActualHeight}}" />
            </TransformGroup>
        </Canvas.RenderTransform>
        <Ellipse Canvas.Left="47" Canvas.Top="48" Height="155" Name="ellipse1" Stroke="Black" Width="174" Fill="#FF00C6C3" />

The problem is this don't compile :

ConverterParameter={Binding Path=ActualHeight}

So I want to know how to move these properties as parameters for my converter? Is it possible to resolve in full Xaml ?

Many thanks for your Help !

Converter source code :

public class ScaleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double v = (double)value;
        var actualSize = (double)parameter; //ActualWidth, ActualHeight

        var vScale = v * (1 + (v / actualSize));

        return vScale;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
A: 

Unfortunately, I do not think that this is possible. Since Binding.ConverterParameter isn't a DependencyProperty, you can't use bindings to populate its value. I've tried to do this before (using a binding for the ConverterParameter) and ran into the same problems that you did.

Andy
+1  A: 

I think you could probably figure out a way to make this work, by making ScaleConverter descend from DependencyObject, giving it an ActualSize dependency property, putting two instances of it in your resources instead of one, and doing a one-way-to-source binding to bind one instance's ActualSize to the canvas's ActualWidth and the other to its ActualHeight (so the instance's ActualSize is always kept in sync with the canvas's width/height as the canvas resizes).

However, it kind of looks like you may actually want something simple: to stretch the canvas to fill its parent. If that's the case, look at Viewbox:

<Viewbox Stretch="Fill">
    <Canvas Width="221" Height="203">
        <Ellipse Canvas.Left="47" Canvas.Top="48" Height="155"
                 Stroke="Black" Width="174" Fill="#FF00C6C3" />
    </Canvas>
</Viewbox>

I included Stretch="Fill" to stretch both X and Y without preserving aspect ratio, since that looked like what you were after. You also need to assign a Width and Height to the Canvas to get that to work, since Canvas doesn't have a natural size by default. The above snippet sets a Width and Height that would put your ellipse at the lower-right corner of the stretched Viewbox; you might want something different than that.

One possible downside to a Viewbox would be that the stroke thicknesses are scaled too, so if you made the window short and wide, the horizontal strokes would be skinny and the vertical strokes would be thick. If that's a problem, you may need to stick with databinding.

Joe White