2011-03-25 83 views
1

我使用了下面的数据模板:一个值转换为多个属性

<DataTemplate> 
    <Grid Width="40" Height="40"> 
     <Ellipse Width="30" Height="30" x:Name="ellipse" /> 
     <TextBlock Text="{Binding Robot.Id}" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
     <Line X1="20" X2="40" X2="20" X2="30" x:Name="line" /> 
    </Grid> 
</DataTemplate> 

我想下面的代码应用到线的时候的DataContext的属性变化:

void UpdateHeading(double angle) 
{ 
    var center = grid.Width/2; 
    var radius = ellipse.Width/2; 
    line.X1 = center + (radius+5)*Math.Sin(angle); 
    line.Y1 = center + (radius+5)*Math.Cos(angle); 
    line.X2 = center + (radius-5)*Math.Sin(angle); 
    line.Y2 = center + (radius-5)*Math.Cos(angle); 
} 

请注意,代码需要访问其他两个元素的大小

添加代码的最佳方式是什么?使用值转换器似乎并不在这里,因为我需要一个属性转换到四个

回答

0

我决定创建自己的形状。

XAML用法:

<Grid Width="40" Height="40"> 
    <Ellipse x:Name="ellipse" Width="30" Height="30" /> 
    <TextBlock Text="{Binding Robot.Id}" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
    <Controls:HeadingLine BoundingSize="40" ShapeSize="30" Length="10" Angle="{Binding Heading}" Stroke="Black" StrokeThickness="1" /> 
</Grid> 

和代码:

public sealed class HeadingLine : Shape 
{ 
    // Properties definitions 
    .... 
    // Code based on http://www.codeproject.com/KB/WPF/wpfarrow.aspx 

    protected override Geometry DefiningGeometry 
    { 
     get 
     { 
      var geometry = new StreamGeometry(); 
      using (var context = geometry.Open()) 
      { 
       InternalDrawArrowGeometry(context); 
      } 

      geometry.Freeze(); 
      return geometry; 
     } 
    } 

    private void InternalDrawArrowGeometry(StreamGeometryContext context) 
    { 
     var center = BoundingSize/2; 
     var radius = ShapeSize/2; 
     var offset = Length/2; 
     var angle = Math.PI - Angle; 

     var x1 = center + (radius + offset) * Math.Sin(angle); 
     var y1 = center + (radius + offset) * Math.Cos(angle); 
     var x2 = center + (radius - offset) * Math.Sin(angle); 
     var y2 = center + (radius - offset) * Math.Cos(angle); 

     context.BeginFigure(new Point(x1, y1), false, false); 
     context.LineTo(new Point(x2, y2), true, true); 
    } 
} 
0

还有一个IMultiValueConverter

编辑: 你应该有一个角属性视图模型,并可以再绑定为以下(我只证明了X1:。

<DataTemplate> 
    <Grid Width="40" Height="40" x:Name="grid"> 
     <Ellipse Width="30" Height="30" x:Name="ellipse" /> 
     <TextBlock Text="{Binding Robot.Id}" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
     <Line X2="40" X2="20" X2="30" x:Name="line"> 
      <Line.X1> 
       <MultiBinding Converter="{StaticResource yourConverter}" ConverterParameter="{yourns:Enum"> 
        <Binding ElementName=grid Path=Width /> 
        <Binding ElementName=ellipse Path=Width /> 
        <Binding Path=Angle /> 
       </MultiBinding> 
      </Line.X1> 
     </Line>  
    </Grid> 
</DataTemplate> 
+0

其中多个值转换为一个属性... – kshahar 2011-03-25 19:50:26

+0

我已经更新我的答案。 – Trantinator 2011-03-25 20:00:09

+0

谢谢你的例子。通过下面的示例,我将不得不在XAML中复制这4次,并使用4个转换器或传递目标类型(X1/Y1/X2/Y2)作为参数。有没有更好的方法来实现这个目标? – kshahar 2011-03-25 20:09:15

0

在你的类所提供的DataContext执行INotifyPropertyChanged并为需要更新然后,只需绑定到这些属性的所有值公开属性的p roperties可以计算出他们需要的任何值,并且UI将得到更新。

例如:

public class Heading : INotifyPropertyChanged 
{ 
    private string name = ""; 
    public string Name { get { return name; } set { name = value; SendPropertyChanged("Name"); } } 
    public int Radius { get { return GridWidth/2; } } 
    public double X1 { get { return Center + (Radius + 5) * Math.Sin(Angle); } } 
    public double X2 { get { return Center + (Radius + 5) * Math.Cos(Angle); } } 
    public double Y1 { get { return Center + (Radius - 5) * Math.Sin(Angle); } } 
    public double Y2 { get { return Center + (Radius - 5) * Math.Cos(Angle); } } 
    public int Center { get { return GridWidth/2; } } 

    private int gridWidth = 50; 
    public int GridWidth { get { return gridWidth; } set { gridWidth = value; } } 

    private double angle; 
    public double Angle { get { return angle; } set { angle = value; SendPropertyChanged(""); } } //Empty string to notify of all properties 

    public event PropertyChangedEventHandler PropertyChanged; 
    void SendPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

然后,只需设置在你模板,因此结合:

<DataTemplate> 
    <Grid > 
     <Ellipse Width="{Binding GridWidth}" Height="40" x:Name="ellipse" Fill="Green" /> 
     <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
     <Line X1="{Binding X1}" X2="{Binding X2}" Y1="{Binding Y1}" Y2="{Binding Y2}" x:Name="line" Stroke="Black" /> 
    </Grid> 
</DataTemplate> 

希望这有助于。