WPF - Связывание и RenderTransform - PullRequest
2 голосов
/ 27 июня 2009

Я хотел бы привязать преобразование scaleTransform к преобразователю, передавшему ActualWidth или ActualHeight.

Вот что я хочу сделать:

<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 ]

3 голосов
/ 28 июня 2009

Я думаю, что вы, вероятно, могли бы найти способ сделать эту работу, сделав 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 без сохранения соотношения сторон, так как это выглядело так, как вы хотели. Вам также нужно назначить ширину и высоту холсту, чтобы заставить это работать, поскольку холст по умолчанию не имеет естественного размера. Вышеупомянутый фрагмент устанавливает ширину и высоту, которые поместили бы ваш эллипс в нижний правый угол растянутого окна просмотра; возможно, вы захотите чего-то другого.

Одним из возможных недостатков Viewbox может быть масштабирование толщины обводки, поэтому, если вы сделаете окно коротким и широким, горизонтальные обводки будут худыми, а вертикальные обводки будут толстыми. Если это проблема, вам может потребоваться привязать данные.

2 голосов
/ 21 марта 2013

РЕДАКТИРОВАТЬ: Все, что я отвечаю, это рефакторинг вашего кода для его компиляции. Если ваше решение не работает, то и это не будет.

Вместо IValueConverter используйте IMultiValueConverter и MultiBinding. Вместо того, чтобы передавать это дополнительное значение как 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();
    }
}
0 голосов
/ 27 июня 2009

К сожалению, я не думаю, что это возможно. Поскольку Binding.ConverterParameter не является DependencyProperty, вы не можете использовать привязки для заполнения его значения. Я пытался сделать это раньше (используя привязку для ConverterParameter) и столкнулся с теми же проблемами, что и вы.

...