I was using Visual Studio to chart data when I ran into a problem with the logarithmic X-Axis. I have now turned to OxyPlot, however, I am running into huge issues with getting my data to populate. I switched from the windows forms to WPF, so this could be a XAML issue with binding (unsure). Essentially I took their very limited example in VB.net and can easily reproduce it. What I am struggling with is reproducing dynamic plotting with OxyPlot. Here is my code so far:
Sample: (http://docs.oxyplot.org/en/latest/getting-started/hello-wpf-vb.html)
Public Sub New()
Model = New PlotModel()
Model.Title = "Simple example"
Model.Subtitle = "using OxyPlot in VB.NET"
Dim series1 = New LineSeries()
series1.Title = "Series 1"
series1.MarkerType = MarkerType.Circle
series1.Points.Add(New DataPoint(0, 0))
series1.Points.Add(New DataPoint(10, 18))
series1.Points.Add(New DataPoint(20, 12))
series1.Points.Add(New DataPoint(30, 8))
series1.Points.Add(New DataPoint(40, 15))
Dim series2 = New LineSeries()
series2.Title = "Series 2"
series2.MarkerType = MarkerType.Square
series2.Points.Add(New DataPoint(0, 4))
series2.Points.Add(New DataPoint(10, 12))
series2.Points.Add(New DataPoint(20, 16))
series2.Points.Add(New DataPoint(30, 25))
series2.Points.Add(New DataPoint(40, 5))
Model.Series.Add(series1)
Model.Series.Add(series2)
End Sub
Then I attempt to add more data to simulate dynamically loading data. I also am aware that I must use invalidate() and that Update() is deprecated. I added a button to the form and give it another series to add to the chart upon click.
Button Click:
Private Sub test_Click(sender As Object, e As RoutedEventArgs) Handles test.Click
Dim series3 = New LineSeries()
series3.Title = "Series 3"
series3.MarkerType = MarkerType.Square
series3.Points.Add(New DataPoint(20, 20))
series3.Points.Add(New DataPoint(21, 21))
series3.Points.Add(New DataPoint(22, 22))
series3.Points.Add(New DataPoint(23, 23))
series3.Points.Add(New DataPoint(24, 24))
Model.Series.Add(series3)
Model.InvalidatePlot(True)
End Sub
Here is also their lovely reference to updating their dataPlot: http://docs.oxyplot.org/en/latest/common-tasks/refresh-plot.html#examples
In your event handler, you need to add series3 to your Model before calling InvalidatePlot i.e.
Model.Series.Add(series3);
Model.InvalidatePlot(true);
Update
Also, you need to make sure your PlotModel notifies the view (XAML) of your changes. If I use the example from Oxyplot documentation as an example (the one you specified), I'd modify the code as such:
Public Class MainViewModel Implements INotifyPropertyChanged
Private mmodel As PlotModel
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Public Sub New()
Model = New PlotModel()
Model.Title = "Simple example"
Model.Subtitle = "using OxyPlot in VB.NET"
Dim series1 = New LineSeries()
series1.Title="Series 1"
series1.MarkerType = MarkerType.Circle
series1.Points.Add(New DataPoint(0, 0))
series1.Points.Add(New DataPoint(10, 18))
series1.Points.Add(New DataPoint(20, 12))
series1.Points.Add(New DataPoint(30, 8))
series1.Points.Add(New DataPoint(40, 15))
Dim series2 = New LineSeries()
series2.Title="Series 2"
series2.MarkerType = MarkerType.Square
series2.Points.Add(New DataPoint(0, 4))
series2.Points.Add(New DataPoint(10, 12))
series2.Points.Add(New DataPoint(20, 16))
series2.Points.Add(New DataPoint(30, 25))
series2.Points.Add(New DataPoint(40, 5))
Model.Series.Add(series1)
Model.Series.Add(series2)
End Sub
Property Model() As PlotModel
Get
Return mmodel
End Get
Set(value As PlotModel)
mmodel = value
NotifyPropertyChanged("Model")
End Set
End Property
Private Sub test_Click(sender As Object, e As RoutedEventArgs) Handles test.Click
Dim series3 = New LineSeries()
series3.Title = "Series 3"
series3.MarkerType = MarkerType.Square
series3.Points.Add(New DataPoint(20, 20))
series3.Points.Add(New DataPoint(21, 21))
series3.Points.Add(New DataPoint(22, 22))
series3.Points.Add(New DataPoint(23, 23))
series3.Points.Add(New DataPoint(24, 24))
Model.Series.Add(series3)
Model.InvalidatePlot(True)
End Sub
End Class
Related
I created this class named "CInventory". This class generates an array of "valid data". To see this array on a range I tried to "paste" the array to see the result. I get a "subscript out of range". The error appears on line 6 (cinv.AllocateInventoryData) of the simple module.
This is the Class Module called CInventory:
Option Explicit
Private Path As String
Private TextFileNumber As Integer
Private InventoryData() As String
Public Property Get GetInventoryData() As String
GetInventoryData = InventoryData
End Property
Public Property Let SPath(Text As String)
Path = Text
End Property
Public Sub AllocateInventoryData()
Dim ColumnArray() As String
TextFileNumber = FreeFile
Dim FileContent As String
Dim i, j As Integer
j = 0
Open Path For Input As TextFileNumber
FileContent = Input(LOF(TextFileNumber), TextFileNumber)
Close TextFileNumber
ColumnArray() = Split(FileContent, vbCrLf)
For i = LBound(ColumnArray) To UBound(ColumnArray)
If IsValidRow(ColumnArray(i)) Then
ReDim Preserve InventoryData(j, 4)
InventoryData(j, 0) = Left(ColumnArray(i), 8)
InventoryData(j, 1) = Trim(Mid(ColumnArray(i), 10, 8))
InventoryData(j, 2) = Trim(Mid(ColumnArray(i), 19, 18))
InventoryData(j, 3) = Trim(Mid(ColumnArray(i), 57, 2))
InventoryData(j, 4) = Trim(Mid(ColumnArray(i), 60, 12))
j = j + 1
End If
Next i
End Sub
Private Function IsValidRow(Text As String) As Boolean
If Left(Text, 6) = "iclorp" Or Left(Text, 5) = "Page:" Or Len(Trim(Text)) < 3 _
Or Left(Text, 4) = "Site" Or Left(Text, 6) = "------" Then
IsValidRow = False
Else
IsValidRow = True
End If
End Function
And this is the Module from which I call the class CInventory (simple module)
Option Explicit
Sub example()
Dim cinv As CInventory
Set cinv = New CInventory
cinv.SPath = "H:\Joel\invent_2.prn"
cinv.AllocateInventoryData '<-- here appears the error
Worksheets(1).Cells(1, 1) = cinv.GetInventoryData
End Sub
here is the answer!, after a while but it works as I wanted
The class module 'CInventory'
Option Explicit
Private Path As String
Private TextFileNumber As Integer
Private InventoryData() As String
Private UBoundInventoryDataRows As Integer
Private UBoundInventoryDataColumns As Integer
Public Property Get GetUBoundInventoryDataRows() As Integer
GetUBoundInventoryDataRows = UBoundInventoryDataRows
End Property
Public Property Get GetUBoundInventoryDataColumns() As Integer
GetUBoundInventoryDataColumns = UBoundInventoryDataColumns
End Property
Public Property Get GetInventoryData() As String()
GetInventoryData = InventoryData
End Property
Public Property Let SPath(Text As String)
Path = Text
End Property
Public Sub AllocateInventoryData()
Dim tempArray() As String
Dim TempLineArray() As String
Dim ColumnArray() As String
Dim FileContent As String
Dim i, j As Integer
TextFileNumber = FreeFile
j = 0
Open Path For Input As TextFileNumber
FileContent = Input(LOF(TextFileNumber), TextFileNumber)
Close TextFileNumber
ColumnArray() = Split(FileContent, vbCrLf)
For i = LBound(ColumnArray) To UBound(ColumnArray)
If LCase(Left(Trim(ColumnArray(i)), 2)) = "mx" Then
ReDim Preserve tempArray(j)
tempArray(j) = Trim(Left(ColumnArray(i), 9)) & ":" & _
Trim(Mid(ColumnArray(i), 10, 9)) & ":" & _
Trim(Mid(ColumnArray(i), 19, 18)) & ":" & _
Trim(Mid(ColumnArray(i), 37, 20)) & ":" & _
Trim(Mid(ColumnArray(i), 57, 4)) & ":" & _
Trim(Mid(ColumnArray(i), 61, 12)) & ":" & _
Trim(Mid(ColumnArray(i), 73, 9)) & ":" & _
Trim(Mid(ColumnArray(i), 82, 9)) & ":" & _
Trim(Mid(ColumnArray(i), 91, 8)) & ":" & _
Trim(Mid(ColumnArray(i), 99, 6)) & ":" & _
Trim(Mid(ColumnArray(i), 105, 9)) & ":" & _
Trim(Mid(ColumnArray(i), 114, 6)) & ":" & _
Trim(Mid(ColumnArray(i), 120, 4)) & ":" & _
Trim(Mid(ColumnArray(i), 124, 3))
j = j + 1
End If
Next i
'in a normal module we shall transpose this next array.
'I did this in this way because of redim agreement
' "the last dimension only could be re-dimensioned"
ReDim InventoryData(13, UBound(tempArray))
For i = LBound(tempArray) To 13
For j = LBound(tempArray) To UBound(tempArray)
TempLineArray = Split(tempArray(j), ":")
InventoryData(i, j) = TempLineArray(i)
Next j
Next i
UBoundInventoryDataRows = UBound(InventoryData, 1)
UBoundInventoryDataColumns = UBound(InventoryData, 2)
End Sub
and here the simple module
Option Explicit
Sub example()
Dim cinv As CInventory
Set cinv = New CInventory
cinv.SPath = "H:\Joel\invent_2.prn"
cinv.AllocateInventoryData
Dim row, column As Integer
row = cinv.GetUBoundInventoryDataRows
column = cinv.GetUBoundInventoryDataColumns
Dim Destination As Range
Set Destination = Range("a1")
Destination.Resize(column, row).Value = Application.Transpose(cinv.GetInventoryData)
Set cinv = Nothing
End Sub
I am trying to create a WPF windows application where it has to show all the Racks or shelves of Warehouse like below
So far this is what I have tried
My Xaml looks like
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="950" Width="1225" BorderBrush="DodgerBlue" BorderThickness="3">
<Grid>
<Canvas Height="900" Width="1200" Name="front_canvas" Grid.Row="0" Grid.Column="0" Margin="1,24,10,790" >
<Canvas.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</Window>
In a Method I have following
For i As Integer = 1 To front_canvas.Width - 1 Step 100
Dim rect As New Rectangle()
rect.StrokeThickness = 1
rect.Stroke = System.Windows.Media.Brushes.Black
rect.Width = 50
rect.Height = 50
rect.Name = "box" + i.ToString()
'If Not i / 2 = 0 Then
Canvas.SetLeft(rect, i)
Canvas.SetFlowDirection(rect, Windows.FlowDirection.LeftToRight)
'Canvas.SetTop(rect, Top)
'_top += rect.Height
If front_canvas.Children.Count > 0 Then
Dim lastChildIndex = front_canvas.Children.Count - 1
Dim lastChild = TryCast(front_canvas.Children(lastChildIndex), FrameworkElement)
If lastChild IsNot Nothing Then
_top = Canvas.GetTop(lastChild) + lastChild.Height + 1
End If
End If
Canvas.SetTop(rect, _top)
front_canvas.Children.Add(rect)
' End If
_rectangles.Add(rect)
Next
And the result I get here is like below
I would appreciate if someone can help me
Here try this:
XAML
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication7"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas Name="cvsWarehouse"></Canvas>
</ScrollViewer>
Code Behind:
Imports System.Text
Class MainWindow
Private Const dRACKSIZE As Double = 57
Private Const dRACKSPACING As Double = 2
Private Const dAISLESPACING As Double = 40
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
CreateAisles()
End Sub
Private Sub CreateAisles()
cvsWarehouse.Width = 10 + (11 * dRACKSIZE) + (6 * dRACKSPACING) + (4 * dAISLESPACING)
cvsWarehouse.Height = 10 + (19 * dRACKSIZE) + (18 * dRACKSPACING)
Dim dStartX As Double = 10
CreateAisle(dStartX, 10, 19, 2, 1)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 2, 2)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 2, 3)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 2, 4)
dStartX += dAISLESPACING
CreateAisle(dStartX, 10, 19, 3, 5)
End Sub
Private Sub CreateAisle(ByRef dStartX As Double, dStarty As Double, iRowCount As Integer, iColCount As Integer, iAisleNumber As Integer)
Dim iColUpper = iColCount - 1
Dim iRowUpper = iRowCount - 1
For iCol As Integer = 0 To iColUpper
Dim dYOffset As Double = dStarty
For iRow As Integer = 0 To iRowUpper
Dim bdr As Border = GetNewBorder()
bdr.Child = GetNewTextBlock(iAisleNumber, iCol + 1, iRow + 1)
Canvas.SetTop(bdr, dYOffset)
Canvas.SetLeft(bdr, dStartX)
cvsWarehouse.Children.Add(bdr)
dYOffset += dRACKSIZE + dRACKSPACING
Next
dStartX += dRACKSIZE + dRACKSPACING
Next
dStartX -= dRACKSPACING
End Sub
Private Function GetNewBorder() As Border
Dim bdr As New Border
bdr.Width = dRACKSIZE
bdr.Height = dRACKSIZE
bdr.BorderBrush = Brushes.Red
bdr.BorderThickness = New Thickness(1)
bdr.CornerRadius = New CornerRadius(2)
Return bdr
End Function
Private Function GetNewTextBlock(iAisle As Integer, iCol As Integer, iRow As Integer) As TextBlock
Dim txtBlock As New TextBlock()
txtBlock.HorizontalAlignment = HorizontalAlignment.Center
txtBlock.VerticalAlignment = VerticalAlignment.Center
Dim sb As New StringBuilder()
sb.Append("A").Append(iAisle.ToString()).Append(":C").Append(iCol.ToString()).Append(":R").Append(iRow.ToString())
txtBlock.Text = sb.ToString()
Return txtBlock
End Function
End Class
if you want to use buttons instead of borders that have event handlers attached:
Private Sub CreateAisle(ByRef dStartX As Double, dStarty As Double, iRowCount As Integer, iColCount As Integer, iAisleNumber As Integer)
Dim iColUpper = iColCount - 1
Dim iRowUpper = iRowCount - 1
For iCol As Integer = 0 To iColUpper
Dim dYOffset As Double = dStarty
For iRow As Integer = 0 To iRowUpper
Dim btn As Button = GetNewButton()
btn.Content = GetNewTextBlock(iAisleNumber, iCol + 1, iRow + 1)
Canvas.SetTop(btn, dYOffset)
Canvas.SetLeft(btn, dStartX)
cvsWarehouse.Children.Add(btn)
dYOffset += dRACKSIZE + dRACKSPACING
Next
dStartX += dRACKSIZE + dRACKSPACING
Next
dStartX -= dRACKSPACING
End Sub
Private Function GetNewButton() As Button
Dim btn As New Button
btn.Width = dRACKSIZE
btn.Height = dRACKSIZE
btn.BorderBrush = Brushes.Red
btn.BorderThickness = New Thickness(1)
btn.AddHandler(Button.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
Return btn
End Function
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim buttonClicked As Button = DirectCast(sender, Button)
Dim text As String = DirectCast(buttonClicked.Content, TextBlock).Text
MessageBox.Show("Button " & text & " Clicked")
End Sub
To the questions below in answer 1, Here is what I did. Most of the code is from SO but it is not actually doing the styles like width and height. Print Preview is done in the following way. I had a Print preview button in tool bar of XAML mainwindow and in code behind I had below code `
Friend Sub DoPreview(title As String)
Dim fileName As String = System.IO.Path.GetRandomFileName()
' Dim visual As FlowDocumentScrollViewer = DirectCast(Me.FindName("cvsWarehouse"), FlowDocumentScrollViewer)
Dim visual As Canvas = DirectCast(cvsWarehouse, Canvas)
visual.Width = 1500
visual.Height = 900
Try
' write the XPS document
Using doc As New XpsDocument(fileName, FileAccess.ReadWrite)
Dim writer As XpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(doc)
writer.Write(visual)
End Using
' Read the XPS document into a dynamically generated
' preview Window
Using doc As New XpsDocument(fileName, FileAccess.Read)
Dim fds As FixedDocumentSequence = doc.GetFixedDocumentSequence()
Dim s As String = _previewWindowXaml
s = s.Replace("##TITLE", title.Replace("'", "'"))
Using reader = New System.Xml.XmlTextReader(New StringReader(s))
Dim preview As New Window
preview.Width = 1500
preview.Height = 900
preview.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
preview.VerticalAlignment = Windows.VerticalAlignment.Stretch
preview = TryCast(System.Windows.Markup.XamlReader.Load(reader), Window)
Dim dv1 As DocumentViewer = TryCast(LogicalTreeHelper.FindLogicalNode(preview, "dv1"), DocumentViewer)
dv1.Width = 1500
dv1.Height = 900
dv1.IsHitTestVisible = True
dv1.VerticalAlignment = Windows.VerticalAlignment.Stretch
dv1.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
dv1.ApplyTemplate()
dv1.Document = TryCast(fds, IDocumentPaginatorSource)
preview.ShowDialog()
End Using
End Using
Finally
If File.Exists(fileName) Then
Try
File.Delete(fileName)
Catch
End Try
End If
End Try
End Sub`
And the my preview is like below
Print Preview Image
Neither I can do scroll bar nor the entire canvas which is wider is fit to the preview window.
My actual Window with canvas is way wider like below
Actual canvas window
Could someone please correct the bug here?
I have a table tenant in my sql 2005 database. It has the following members, where tdoc and tpic are of datatype image:
tid
tname
tadd
tph
tdoc
tpic
I want to insert 2 images from 2 picture boxes to tdoc and tpic using VB.NET.
I managed to write the following code for my record save button. Please help me with further code.
Private Sub bsave_Click(sender As Object, e As EventArgs) Handles bsave.Click
If ((tname.Text = "") Or (tadd.Text = "") Or (tphn.Text = "")) Then
MsgBox("Details are Incomplete", MsgBoxStyle.Exclamation)
Else
conn.Open()
Dim s As String = "Insert into rent values('" & tid & "','" & tname.Text & "','" & tadd.Text & "','" & tphn.Text & "',#doc,#photo)"
MessageBox.Show("Name & Image has been saved", "Save", MessageBoxButtons.OK)
conn.Close()
End If
End Sub
I would like to use a MemoryStream, please just guide me with it.
I have used this logic in my C# project hope it helps you.
using System.IO;
private void **BrowseFile_Click**(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "JPG Files(*.jpg)|*.jpg|PNG Files(*.pnbg)|*.png|All Files(*.*)|*.*";
dlg.Title = " Select Bike Picture";
if (dlg.ShowDialog() == DialogResult.OK)
{
String picLoc = dlg.FileName.ToString();
pictureBox1.ImageLocation = picLoc;
textBox9.Text = picLoc;
}
}
private void **SaveButton_Click**(object sender, EventArgs e)
{
FileStream fs1 =newFileStream(textBox9.Text,System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte[] image = new byte[fs1.Length];
fs1.Read(image, 0, Convert.ToInt32(fs1.Length));
fs1.Close();
con.Open();
SqlCommand cmdupdt = new SqlCommand("Insert into TableName values(#pic )",con);
SqlParameter prm = new SqlParameter("#pic", SqlDbType.VarBinary, image.Length, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, image);
cmdupdt.Parameters.Add(prm);
cmdupdt.ExecuteNonQuery();
con.Close();
}
I have a canvas that shows an audio waveform, which is made using a lot of Lines. Each line is Tagged with it's time code so I can identify where in the audio it is.
I want to put a rectangle on the canvas based on data stored in an observable collection.
Basically, Timespan start and end points so I can show a block of audio.
The problem I'm having is that to show the rectangle, I have to know the Canvas left value and width.
I can get these by scanning through the canvas children until I find the correct line and getting its X1 value, but I don't know how to do it in a binding.
I want to bind the observable collection ItemsControl so I can show the rectangles on the canvas.
Is it possible to bind to a function or something that would do the calculations based on the data in the observable collection?
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>
Creating the waveform:
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
I have a WPF 4/VB.net 2010 project, and I'm trying to do a visual "drag and drop" (having an object follow the mouse on MouseUp and "stick" on MouseDown.) I have the following code behind:
Private Sub Tile1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles Tile1.MouseDown
Tile1.CaptureMouse()
IsDragging = True
End Sub
Private Sub Tile1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs) Handles Tile1.MouseMove
If IsDragging = True Then
Dim canvPosToWindow As Point = canv.TransformToAncestor(Me).Transform(New Point(0, 0))
Dim r As Rectangle = TryCast(sender, Rectangle)
Dim upperlimit As Double = canvPosToWindow.Y + (r.Height / 2)
Dim lowerlimit As Double = canvPosToWindow.Y + canv.ActualHeight - (r.Height / 2)
Dim leftlimit As Double = canvPosToWindow.X + (r.Width / 2)
Dim rightlimit As Double = canvPosToWindow.X + canv.ActualWidth - (r.Width / 2)
Dim absmouseXpos As Double = e.GetPosition(Me).X
Dim absmouseYpos As Double = e.GetPosition(Me).Y
If (absmouseXpos > leftlimit AndAlso absmouseXpos < rightlimit) AndAlso (absmouseYpos > upperlimit AndAlso absmouseYpos < lowerlimit) Then
r.SetValue(Canvas.LeftProperty, e.GetPosition(canv).X - (r.Width / 2))
r.SetValue(Canvas.TopProperty, e.GetPosition(canv).Y - (r.Height / 2))
End If
End If
End Sub
Private Sub Tile1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles Tile1.MouseUp
Tile1.ReleaseMouseCapture()
IsDragging = False
End Sub
I am getting this error:
NullReferenceException, Object reference not set to an instance of an object.
On each of the following lines:
Dim upperlimit As Double = canvPosToWindow.Y + (r.Height / 2)
Dim lowerlimit As Double = canvPosToWindow.Y + canv.ActualHeight - (r.Height / 2)
Dim leftlimit As Double = canvPosToWindow.X + (r.Width / 2)
Dim rightlimit As Double = canvPosToWindow.X + canv.ActualWidth - (r.Width / 2)
What am I doing wrong?
I suspect that this statement makes r "null" and not a proper rectangle.
Dim r As Rectangle = TryCast(sender, Rectangle)
The sender is probably not a rectangle but probably a WPF-Control (some subclass of System.Windows.Controls.Control).
You can easily check with the Visual Studio debugger, by placing a debug-point on this line and see if this statement evaluates.
Good luck with your drag-drop implementation :).