2011-03-25 139 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> 

希望這有助於。