«Относительная» привязка в WPF - PullRequest
1 голос
/ 08 декабря 2010

У меня есть сложная «точка» в WPF, которая мне нужна для настройки диаметра.

alt text

Пример контрольного кода:

<UserControl>
    <Canvas>
        <Canvas.RenderTransform>
            <TranslateTransform X="-6" Y="-6"/>
        </Canvas.RenderTransform>
        <Ellipse Width="12" Height="12" x:Name="BigCircle" Fill="Red"/>
        <Ellipse Width="8" Height="8" x:Name="MediumCircle" Fill="Green" Canvas.Left="2" Canvas.Top="2"/>
        <Ellipse Width="4" Height="4" x:Name="SmallCircle" Fill="Blue" Canvas.Left="4" Canvas.Top="4" />
    </Canvas>
</UserControl>

Чего я хочу достичь:

<UserControl>
    <UserControl.Resources>
        <sys:Double x:Key="dd">120</sys:Double>
    </UserControl.Resources>
    <Canvas>
        <Canvas.RenderTransform>
            <TranslateTransform X="-dd/2" Y="-dd/2"/>
        </Canvas.RenderTransform>
        <Ellipse Width="{DynamicResource ResourceKey=dd}" Height="{DynamicResource ResourceKey=dd}" x:Name="BigCircle" Fill="Red"/>
        <Ellipse Width="dd*2/3" Height="dd*2/3" x:Name="MediumCircle" Fill="Green" Canvas.Left="dd/6" Canvas.Top="dd/6"/>
        <Ellipse Width="dd/3" Height="dd/3" x:Name="SmallCircle" Fill="Blue" Canvas.Left="dd/3" Canvas.Top="dd/3" />
    </Canvas>
</UserControl>

каждый раз, когда я меняю «дд», я хочу, чтобы мои круги пропорционально менялись.

Использование конвертеров

[ValueConversion(typeof(double), typeof(double))]
public class LargeToMediumConverter : IValueConverter 
{

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((double)value * 2) / 3;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
/*  XAML */
<UserControl.Resources>
    <sys:Double x:Key="DotDiameter">12</sys:Double>
</UserControl.Resources>
...
<Ellipse Width="{Binding ElementName=DotDiameter}" Height="{Binding ElementName=DotDiameter}" x:Name="LargeCircle" ...
...

так что это не работает ....

Ответы [ 3 ]

3 голосов
/ 08 декабря 2010

A Converter является опцией.Конвертер выражений в моей библиотеке WPF конвертеры позволит вам вычислить значения на основе выражения:

<sys:Double x:Key="OuterWidth">120</sys:Double>

...

<Ellipse Width="{StaticResource OuterWidth}" .../>
<Ellipse Width="{Binding Source={StaticResource OuterWidth}, Converter={kb:ExpressionConverter 2/3*{0}}}" .../>
<Ellipse Width="{Binding Source={StaticResource OuterWidth}, Converter={kb:ExpressionConverter 1/3*{0}}}" .../>

Другой вариант, если вы используете MVVM, это просто предоставить отдельные свойствас вашей точки зрения модель - одна для ширины каждого эллипса.Затем свяжите их с вашей точки зрения:

<Ellipse Width="{Binding LargeWidth}" .../>
<Ellipse Width="{Binding MediumWidth}" .../>
<Ellipse Width="{Binding SmallWidth}" .../>
3 голосов
/ 11 декабря 2010

Вау!Вы все слишком усердно работаете. WPF может сделать ваш макет за вас и легко.

Это будет делать именно то, что вы ищете, без конвертеров или другого кода любого рода.:

<UserControl>
  <UserControl.Resources>
    <sys:Double x:Key="dd">120</sys:Double>
  </UserControl.Resources>
  <Canvas>
    <Grid Width="2000000" Height="2000000" RenderTransform="1 0 0 1 -1000000 -1000000">
      <Viewbox Width="{DynamicResource dd}" Height="{DynamicResource dd}" VerticalAlignment="Center" HorizontalAlignment="Center">
        <Grid Width="12" Height="12">
          <Ellipse Width="12" Height="12" Fill="Red" HorizontalAlignment="Center" VerticalAlignment="Center"/>
          <Ellipse Width="8" Height="8" Fill="Green" HorizontalAlignment="Center" VerticalAlignment="Center"/>
          <Ellipse Width="4" Height="4" Fill="Blue" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
      </Viewbox>
    </Grid>
  </Canvas>
</UserControl>

Это только один из многих способов сделать это.

Как это работает

  • Внутренняя Сетка и еевсе три эллипса имеют фиксированный размер и положение.
  • Viewbox изменяет размер бычьего глаза до желаемого размера.
  • Внешняя сетка центрирует бычий глаз в (0,0).Это удобная идиома для центрирования: создайте квадрат размером 2 миллиона, отцентрируйте объект в сетке, а затем преобразуйте его на 1 миллион в центр.
  • Холст предотвращает отсечение.

Обратите внимание, что бычий глаз также можно легко сделать с помощью чертежа: просто замените окно просмотра прямоугольником, кисть Fill которого является рисунком бычьего глаза.Использование чертежа было бы более эффективным, но менее гибким (без возможности анимировать эллипсы и т. Д.).

Конвертеры имеют свое место, но обычно лучше позволить WPF сделать макет для вас, особенно в простых случаях.как это.Даже в сложных случаях я рекомендую людям писать Panel, которая делает их собственный макет вместо использования конвертеров.

1 голос
/ 08 декабря 2010

Вам нужен BindingConverter.Посмотрите следующий учебник для более подробной информации.
Вы не можете привязать математические выражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...