简体   繁体   English

WPF中的“相对”绑定

[英]“Relative” Binding in WPF

I have a complex "Dot" in WPF which I need to customize the diameter. 我在WPF中有一个复杂的“点”,需要自定义直径。

替代文字

The control code sample: 控制代码示例:

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

What I want to achieve: 我要实现的目标:

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

every time I change "dd" then I want that my circles proportionally changes. 每次更改“ dd”时,我都希望我的圈子按比例更改。

Using Converters 使用转换器

[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" ...
...

so this does not work.... 所以这行不通...

A Converter is an option. Converter是一个选项。 The expression converter in my WPF converters library will allow you to calculate values based on an expression: 我的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}}}" .../>

Another option, if you're doing MVVM, is to just expose separate properties from your view model - one for the width of each ellipse. 如果您正在执行MVVM,另一种选择是仅从视图模型中公开单独的属性-一个用于表示每个椭圆的宽度。 Then bind to them in your view: 然后绑定到您的视图中:

<Ellipse Width="{Binding LargeWidth}" .../>
<Ellipse Width="{Binding MediumWidth}" .../>
<Ellipse Width="{Binding SmallWidth}" .../>

Wow! 哇! You all are working way too hard. 你们都太努力了。 WPF can do your layout for you, and easily too. WPF可以轻松地为您做布局。

This will do exactly what you are looking for with no converters or other code of any kind: 无需任何转换器或任何其他代码,这将完全满足您的期望:

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

This is only one of many ways to do it. 这只是许多方法之一。

How it works 这个怎么运作

  • The inner Grid and its three Ellipses are all in a fixed size and position. 内部网格及其三个椭圆都处于固定的大小和位置。
  • The Viewbox resizes the bulls-eye to the desired size. Viewbox将靶心调整为所需的大小。
  • The outer Grid centers the bulls-eye at (0,0). 外部网格将靶心定在(0,0)。 This is a convenient idiom for centering: Create a grid 2-million square, center the object in the grid, and then transform it by 1-million to the center. 这是居中的方便用法:创建一个200万平方的网格,将对象在网格中居中,然后将其转换100万到中心。
  • The Canvas prevents clipping. 画布可防止修剪。

Note that the bulls-eye can also easily be done with a Drawing: Just replace the Viewbox with a Rectangle whose Fill brush is the drawing of the bulls-eye. 请注意,也可以通过工程图轻松实现靶心图:只需将Viewbox替换为矩形,其矩形的Fill画笔就是靶心图。 Using a Drawing would be more efficient but less flexible (no ability to animate the ellipses, etc). 使用工程图会更有效,但灵活性更差(无法对椭圆进行动画处理等)。

Converters have their place, but it is usually best to let WPF do the layout for you, especially in simple cases like this. 转换器有自己的位置,但是通常最好让WPF为您做布局,尤其是在像这样的简单情况下。 Even in complex cases I recommend people write a Panel that does their custom layout instead of using converters. 即使在复杂的情况下,我也建议人们编写一个面板来执行其自定义布局,而不要使用转换器。

You need a BindingConverter . 您需要一个BindingConverter Check out the following tutorial for more details. 请查看以下教程以了解更多详细信息。
You cant bind to mathematical expressions. 您不能绑定到数学表达式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM