WPF - 绑定和RenderTransform

时间:2009-06-27 18:06:34

标签: wpf xaml binding actualwidth actualheight

我想将scaleTransform绑定到通过ActualWidthActualHeight的转换器。

这就是我想要做的事情:

<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" />

问题是这不能编译:

ConverterParameter={Binding Path=ActualHeight}

所以我想知道如何将这些属性作为转换器的参数移动?是否有可能完全解决Xaml?

非常感谢您的帮助!

转换器源代码:

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();
    }
}

3 个答案:

答案 0 :(得分:3)

我认为你可以通过使ScaleConverter从DependencyObject下降,给它一个ActualSize依赖属性,将它的两个实例放在你的资源中而不是一个,并且做一个单向源绑定将一个实例的ActualSize绑定到画布的ActualWidth,另一个绑定到它的ActualHeight(因此实例的ActualSize始终与画布的宽度/高度保持同步作为画布调整大小)。

然而,看起来你可能真的想要一些简单的东西:拉伸画布以填充其父级。如果是这种情况,请查看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>

我包括Stretch="Fill"来拉伸X和Y而不保留纵横比,因为这看起来就像你所追求的那样。您还需要为“画布”指定“宽度”和“高度”以使其起作用,因为默认情况下Canvas没有自然大小。上面的代码片段设置了一个宽度和高度,可以将椭圆放在拉伸的Viewbox的右下角;你可能想要不同的东西。

Viewbox的一个可能的缺点是笔划厚度也会缩放,所以如果你使窗口变短和宽,水平笔划将是粗糙的,垂直笔划将是厚的。如果这是一个问题,您可能需要坚持使用数据绑定。

答案 1 :(得分:2)

编辑:我的所有答案都是重构你的代码以便编译。如果你的解决方案不起作用,那么这也不会。

不使用IValueConverter,而是使用IMultiValueConverterMultiBinding。不是将该额外值作为ConverterParameter传递,而是将其作为额外绑定传递。

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

你的转换器:

public class ScaleConverter : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double v = (double)values[0];
        var actualSize = (double)values[1]; //ActualWidth, ActualHeight

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

        return vScale;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

答案 2 :(得分:0)

不幸的是,我不认为这是可能的。由于Binding.ConverterParameter不是DependencyProperty,因此您无法使用绑定来填充其值。我之前尝试过(使用ConverterParameter的绑定)并遇到了与你相同的问题。