none
Text an eine drehende Linie binden RRS feed

  • Frage

  • Ich habe Linien zwischen Verschiedenen ScatterViewItems. Diese Linien sollen einen Text bekommen. Das Problem ist das Line keinen Text vorsieht :(

    <ItemsControl ItemsSource="{Binding Path=Items}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type vm:ItemViewModel}">
                            <Line Stroke="Black"
                              X1="{Binding Position.X}"
                              Y1="{Binding Position.Y}"
                              X2="{Binding Next.Position.X}"
                              Y2="{Binding Next.Position.Y}" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

    Gibt es eine Möglickeit einen kurzen Text an diese Linien zu schreiben?

    Freitag, 16. November 2012 10:09

Antworten

  • Hier mal eine Demo, wie ich das meine:

    XAML

    <Window x:Class="Window03"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window03" Height="1000" Width="1000">
      <Canvas>
        <StackPanel Orientation="Horizontal">
          <Label Content="X: "/>
          <Slider Width="200" Value="{Binding X, Mode=TwoWay}" Minimum="20" Maximum="1000"/>
          <Label Content="Y: "/>
          <Slider Width="200" Value="{Binding Y, Mode=TwoWay}" Minimum="20" Maximum="1000"/>
          <Label Content="Winkel: "/>
          <Slider Width="200" Value="{Binding Winkel, Mode=TwoWay}" Minimum="0" Maximum="360"/>
        </StackPanel>
        <Canvas>
          <Canvas.RenderTransform>
            <MatrixTransform Matrix="{Binding TransMatrix}"/>
          </Canvas.RenderTransform>
          <Label Content="Linientext" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Width="100" Height="40"/>
          <Line X1="0" Y1="40" X2="100" Y2="40" Stroke="Black" StrokeThickness="2"/>
        </Canvas>
      </Canvas>
    </Window>
    

    Dazu der Code:

    Imports System.ComponentModel
    
    Public Class Window03
    
      Private Sub Window03_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Me.DataContext = New ViewModel03
      End Sub
    
    End Class
    
    Public Class ViewModel03
      Implements INotifyPropertyChanged
    
      Private _x As Double = 50
      Public Property X As Double
        Get
          Return Me._x
        End Get
        Set(value As Double)
          Me._x = value
          OnPropertyChanged("TransMatrix")
        End Set
      End Property
    
      Private _y As Double = 50
      Public Property Y As Double
        Get
          Return Me._y
        End Get
        Set(value As Double)
          Me._y = value
          OnPropertyChanged("TransMatrix")
        End Set
      End Property
    
      Private _winkel As Double
      Public Property Winkel As Double
        Get
          Return Me._winkel
        End Get
        Set(value As Double)
          Me._winkel = value
          OnPropertyChanged("TransMatrix")
        End Set
      End Property
    
      Public ReadOnly Property TransMatrix As Matrix
        Get
          Dim ma As New Matrix(1, 0, 0, 1, 0, 0)
          ma.Rotate(Me._winkel)
          Dim wi = Math.PI * Me._winkel / 180
          ma.OffsetX = Me._x - 50 * Math.Cos(wi) + 20 * Math.Sin(wi)
          ma.OffsetY = Me._y - 20 * Math.Cos(wi) - 50 * Math.Sin(wi)
          Return ma
        End Get
      End Property
    
      Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    
      Private Sub OnPropertyChanged(propName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
      End Sub
    
    End Class
    

    --
    Viele Gruesse
    Peter

    • Als Antwort markiert egon56 Montag, 19. November 2012 14:15
    Samstag, 17. November 2012 17:28

Alle Antworten

  • Hallo egon56,

    Vielleicht kannst Du zwei Linien haben und ein TextBlock zwischen. Oder musst Du ein eigenes UserControl entwickeln. Hier habe ich ein Link gefunden vielleicht kann es Dir weiterhelfen.

    Gruß,

    Ionut

    Freitag, 16. November 2012 16:40
    Moderator
  • Da Du ja im ViewModel alles berechnest, berechne doch dort gleich eine Transformationsmatrix. Mit dieser kannst Du sowohl Text als auch Line neu positionieren.
     
    --
    Viele Gruesse
    Peter
    Freitag, 16. November 2012 19:57
  • @Ionut Duma

    Mit den zwei Linien und dem TextBlock habe ich zuerst auch gedacht, aber man kann keine zwei Objekte (bzw. drei Objekte) in das DataTemplate packen. Da ist es sehr unschön, dass die Linie keinen Text aufnehmen kann wie <Line ...><TextBlock /></Linie> oder sogar die Linie ein Textfeld hätte.

    Der Link ist schon ein guter Ansatz, aber viel zu Umfangreich wie ich es benötige. Dort wird Text ja sogar auf einer beliebig verdrehten Linie geschrieben. Im meinem Fall habe ich eine relativ einfache und gerade Linie.

    Kann ich ein UserControl genau an dieser Stelle wieder einbinden? Also als ein Objekt? Würde der Text auch mit gedreht?
    • Bearbeitet egon56 Samstag, 17. November 2012 10:18
    Samstag, 17. November 2012 09:50
  • @Peter Fleischer

    Hast du dafür vielleicht ein Beispiel?

    • Bearbeitet egon56 Samstag, 17. November 2012 10:18
    Samstag, 17. November 2012 09:51
  • Hier mal eine Demo, wie ich das meine:

    XAML

    <Window x:Class="Window03"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window03" Height="1000" Width="1000">
      <Canvas>
        <StackPanel Orientation="Horizontal">
          <Label Content="X: "/>
          <Slider Width="200" Value="{Binding X, Mode=TwoWay}" Minimum="20" Maximum="1000"/>
          <Label Content="Y: "/>
          <Slider Width="200" Value="{Binding Y, Mode=TwoWay}" Minimum="20" Maximum="1000"/>
          <Label Content="Winkel: "/>
          <Slider Width="200" Value="{Binding Winkel, Mode=TwoWay}" Minimum="0" Maximum="360"/>
        </StackPanel>
        <Canvas>
          <Canvas.RenderTransform>
            <MatrixTransform Matrix="{Binding TransMatrix}"/>
          </Canvas.RenderTransform>
          <Label Content="Linientext" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Width="100" Height="40"/>
          <Line X1="0" Y1="40" X2="100" Y2="40" Stroke="Black" StrokeThickness="2"/>
        </Canvas>
      </Canvas>
    </Window>
    

    Dazu der Code:

    Imports System.ComponentModel
    
    Public Class Window03
    
      Private Sub Window03_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Me.DataContext = New ViewModel03
      End Sub
    
    End Class
    
    Public Class ViewModel03
      Implements INotifyPropertyChanged
    
      Private _x As Double = 50
      Public Property X As Double
        Get
          Return Me._x
        End Get
        Set(value As Double)
          Me._x = value
          OnPropertyChanged("TransMatrix")
        End Set
      End Property
    
      Private _y As Double = 50
      Public Property Y As Double
        Get
          Return Me._y
        End Get
        Set(value As Double)
          Me._y = value
          OnPropertyChanged("TransMatrix")
        End Set
      End Property
    
      Private _winkel As Double
      Public Property Winkel As Double
        Get
          Return Me._winkel
        End Get
        Set(value As Double)
          Me._winkel = value
          OnPropertyChanged("TransMatrix")
        End Set
      End Property
    
      Public ReadOnly Property TransMatrix As Matrix
        Get
          Dim ma As New Matrix(1, 0, 0, 1, 0, 0)
          ma.Rotate(Me._winkel)
          Dim wi = Math.PI * Me._winkel / 180
          ma.OffsetX = Me._x - 50 * Math.Cos(wi) + 20 * Math.Sin(wi)
          ma.OffsetY = Me._y - 20 * Math.Cos(wi) - 50 * Math.Sin(wi)
          Return ma
        End Get
      End Property
    
      Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    
      Private Sub OnPropertyChanged(propName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
      End Sub
    
    End Class
    

    --
    Viele Gruesse
    Peter

    • Als Antwort markiert egon56 Montag, 19. November 2012 14:15
    Samstag, 17. November 2012 17:28
  • class ViewModel03 : INotifyPropertyChanged { private Double _x = 50; public Double X { get { return this._x; } set { this._x = value; OnPropertyChanged("Transmatrix"); } } private Double _y = 50; public Double Y { get { return this._y; } set { this._y = value; OnPropertyChanged("Transmatrix"); } } private Double _winkel; public Double Winkel { get { return this._winkel; } set { this._winkel = value; OnPropertyChanged("Transmatrix"); } } public Matrix TransMatrix { get { var ma = new Matrix(1, 0, 0, 1, 0, 0); ma.Rotate(this._winkel); var wi = Math.PI * this._winkel / 100; ma.OffsetX = this._x - 50 * Math.Cos(wi) + 20 * Math.Sin(wi); ma.OffsetY = this._y - 20 * Math.Cos(wi) - 50 * Math.Sin(wi); return ma; } } private void OnPropertyChanged(String propname) { PropertyChanged(this, new PropertyChangedEventArgs(propname)); } public event PropertyChangedEventHandler PropertyChanged; }

    Für alle die hier auch auf das Thema stossen.

    OnPropertyChanged und PropertyChanged musste ich noch anpassen. Trotzdem Danke für das Beispiel.

    Montag, 19. November 2012 14:15
  • Jetzt muss ich nur noch hinbekommen die Linie und den Text zu Gruppieren, den in ItemTemplate -> Datatemplate kann ich immer nur ein Visuelles Element angeben.
    Montag, 19. November 2012 14:32
  • Bin jetzt schon etwas weiter. Aber ich habe immernoch ein Problem mit dem Text. Im Gegensatz zu dem Beispiel ist die Linie bei mir vorgegeben und der Text soll an der Linie bleiben.

    <UserControl ....>
        <Canvas>
            <Canvas.RenderTransform>
                <MatrixTransform Matrix="{Binding TransMatrix}"/>
            </Canvas.RenderTransform>
            <Label Content="Art" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" Height="40" />
            <Line X1="{Binding SourcePosition.Position.X}"
                  Y1="{Binding SourcePosition.Position.Y}"
                  X2="{Binding TargetPosition.Position.X}"
                  Y2="{Binding TargetPosition.Position.Y}"
                  Stroke="Green"
                  Name="line"/>
        </Canvas>
    </UserControl>

    Die Linie soll in dem Fall So bleiben wie sie ist (Verbindet zwei Sachen). Die Elemente sind beweglich und ohne dem Transform passt sich die Linie auch einfach den Elementen und deren Position an.

    Nun soll dieses Label oder ein TextBlock immer genau auf der hälfte der Linien sein. Mit dem Transform werden ja auch die Linien manipuliert.

    Montag, 3. Dezember 2012 15:04