wpf绑定前处理数据

时间:2014-08-14 19:51:20

标签: wpf vb.net wpf-controls

我有一个显示音频波形的画布,它是使用很多行创建的。每一行都标有它的时间码,所以我可以识别它在音频中的位置。

我想根据存储在可观察集合中的数据在画布上放置一个矩形 基本上,Timespan起点和终点,所以我可以显示一个音频块。

我遇到的问题是要显示矩形,我必须知道Canvas左边的值和宽度 我可以通过扫描画布中的子项来获取这些,直到找到正确的行并获得其X1值,但我不知道如何在绑定中执行此操作。

我想绑定可观察的集合ItemsControl,以便我可以在画布上显示矩形。

是否可以绑定到基于可观察集合中的数据进行计算的函数或其他东西?

XAML:

    <ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden">
        <Canvas Name="waveform" >
            <ItemsControl Name="RectArea"> <!-- Where I hope to have the rectangles appear on top of the waveform canvas -->
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Rectangle Stroke="Yellow" Fill="Yellow" Opacity="0.2" Height="200" Width="{Binding Width}" Canvas.Left="{Binding Left}" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Canvas>
    </ScrollViewer>

创建波形:

        Dim seconds As Integer = 0
        lines = New Dictionary(Of String, Line)

        Using Reader As New AudioFileReader(openfile.FileName)
            Dim samples = Reader.Length / (Reader.WaveFormat.Channels * Reader.WaveFormat.BitsPerSample / 8)
            Dim f = 0.0F
            Dim max = 0.0F

            Dim batch As Integer = Math.Max(10, samples / samplecount)
            Dim mid = 100
            Dim yScale = 100

            Dim buffer(batch) As Single

            Dim read As Integer

            Dim xPos = 0
            read = Reader.Read(buffer, 0, batch)
            While read = batch
                For n As Integer = 0 To read
                    max = Math.Max(Math.Abs(buffer(n)), max)
                Next

                Dim line As New Line
                line.X1 = xPos
                line.X2 = xPos
                line.Y1 = mid + (max * yScale)
                line.Y2 = mid - (max * yScale)
                line.Tag = Reader.CurrentTime

                line.StrokeThickness = 1
                line.Stroke = Brushes.DarkGray

                AddHandler line.MouseDown, AddressOf Line_MouseDown

                waveform.Children.Add(line)

                ' lines is a dictionary that holds all of the line information. nothing is bound to it, it just allows me to search against time code so I can highlight the line as the audio is playing' 
                If Not lines.ContainsKey(Reader.CurrentTime.Hours.ToString().PadLeft(2, "0") & Reader.CurrentTime.Minutes.ToString().PadLeft(2, "0") & Reader.CurrentTime.Seconds.ToString().PadLeft(2, "0") & Reader.CurrentTime.Milliseconds.ToString().PadLeft(3, "0").Substring(0, 1)) Then
                    lines.Add(Reader.CurrentTime.Hours.ToString().PadLeft(2, "0") & Reader.CurrentTime.Minutes.ToString().PadLeft(2, "0") & Reader.CurrentTime.Seconds.ToString().PadLeft(2, "0") & Reader.CurrentTime.Milliseconds.ToString().PadLeft(3, "0").Substring(0, 1), line)
                End If

                ' Draw a tall black line and show timecode every 10 seconds to make it easier to see where you are on the code '
                If Reader.CurrentTime.TotalSeconds > (seconds + 10) Then
                    seconds = Reader.CurrentTime.TotalSeconds
                    line = New Line
                    line.X1 = xPos
                    line.X2 = xPos
                    line.Y1 = mid + yScale
                    line.Y2 = mid - yScale

                    line.StrokeThickness = 1
                    line.Stroke = Brushes.Black
                    waveform.Children.Add(line)

                    Dim textblock As New TextBlock
                    textblock.Text = Reader.CurrentTime.Hours.ToString().PadLeft(2, "0") & ":" & Reader.CurrentTime.Minutes.ToString().PadLeft(2, "0") & ":" & Reader.CurrentTime.Seconds.ToString().PadLeft(2, "0") & "," & Reader.CurrentTime.Milliseconds.ToString().PadLeft(3, "0")
                    textblock.Foreground = Brushes.Black
                    Canvas.SetLeft(textblock, xPos)
                    Canvas.SetTop(textblock, yScale)
                    waveform.Children.Add(textblock)
                End If

                max = 0
                xPos += 1
                read = Reader.Read(buffer, 0, batch)
            End While
            waveform.Width = xPos
        End Using

的ObservableCollection:

Imports System.ComponentModel
Imports System.Collections.ObjectModel
Public Class ocAudioSelection
    Implements INotifyPropertyChanged
    Private _Changed As Boolean
    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Protected Overridable Sub OnPropertyChanged(ByVal Propertyname As String)
        On Error GoTo sError

        If Not Propertyname.Contains("Changed") Then
            Changed = True
        End If
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Propertyname))

        Exit Sub
sError:
        MsgBox(ErrorToString)
    End Sub

    Public Property Changed() As Boolean
        Get
            Return _Changed
        End Get
        Set(ByVal value As Boolean)
            If _Changed <> value Then
                _Changed = value
                OnPropertyChanged("Changed")
            End If
        End Set
    End Property

    Private _startTime As String
    Private _endTime As String

    Public Sub New()

    End Sub

    Public Sub New(startTime As String)
        _startTime = startTime
    End Sub

    Public Sub New(startTime As String, endTime As String)
        _startTime = startTime
        _endTime = endTime
    End Sub

    Public Property StartTime As String
        Get
            Return _startTime 
        End Get
        Set(value As String)
            If value <> _startTime Then 
                _startTime = value
                OnPropertyChanged("StartTime")
            End If
        End Set
    End Property

    Public Property EndTime As String
        Get
            Return _endTime 
        End Get
        Set(value As String)
            If value <> _endTime Then 
                _endTime = value 'TimeSpan.Parse()
                OnPropertyChanged("EndTime")
            End If
        End Set
    End Property

End Class

0 个答案:

没有答案