WPF中的“相对”绑定

时间:2010-12-08 17:49:50

标签: .net wpf user-controls

我在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>

每当我改变“dd”,我希望我的圈子按比例改变。

使用转换器

[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 个答案:

答案 0 :(得分:3)

Converter是一个选项。我的WPF converters库中的表达式转换器允许您根据表达式计算值:

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

答案 1 :(得分:3)

哇!你们都非常努力地工作。 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)。这是一个方便的居中习惯:创建一个200万平方的网格,将对象置于网格中心,然后将其转换为100万到中心。
  • Canvas防止剪裁。

请注意,也可以使用绘图轻松完成靶心:只需用一个矩形替换Viewbox,其填充画笔是靶心的绘图。使用绘图会更有效但灵活性更低(没有动画椭圆等功能)。

转换器有它们的位置,但通常最好让WPF为你做布局,特别是在这样的简单情况下。即使在复杂的情况下,我也建议人们编写一个Panel来执行自定义布局,而不是使用转换器。

答案 2 :(得分:1)

您需要BindingConverter。查看following tutorial了解更多详情。
您无法绑定数学表达式。