From de17eb5a22980ecc37ab06dd9bac8e038bc84565 Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sat, 11 Nov 2023 08:33:09 +0100 Subject: [PATCH 01/13] improve performance of values window by using a dataview and binding it to the datagridview --- source/Controllers/ValuesController.vb | 2 + source/Views/ValuesWindow.vb | 147 +++++++++++++++---------- 2 files changed, 88 insertions(+), 61 deletions(-) diff --git a/source/Controllers/ValuesController.vb b/source/Controllers/ValuesController.vb index 36eb620f..2369bfbe 100644 --- a/source/Controllers/ValuesController.vb +++ b/source/Controllers/ValuesController.vb @@ -39,6 +39,8 @@ Friend Class ValuesController AddHandler _model.SeriesAdded, AddressOf UpdateView AddHandler _model.SeriesPropertiesChanged, AddressOf UpdateView AddHandler _model.SeriesRemoved, AddressOf UpdateView + AddHandler _model.SeriesAllReordered, AddressOf UpdateView + AddHandler _model.SeriesReordered, AddressOf UpdateView AddHandler _model.SeriesCleared, AddressOf UpdateView End Sub diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index f090a8a2..3efc108b 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -20,7 +20,10 @@ Friend Class ValuesWindow Implements IView Private isInitializing As Boolean + Private tsList As List(Of TimeSeries) Private dataset As DataSet + Private dataview As DataView + Private databinding As BindingSource Private _controller As ValuesController @@ -63,6 +66,15 @@ Friend Class ValuesWindow Dim table As New DataTable("data") Me.dataset.Tables.Add(table) + 'create the dataview and bind it to the DataGridView + Me.dataview = New DataView(table) + Me.databinding = New BindingSource With { + .DataSource = Me.dataview + } + Me.DataGridView1.DataSource = Me.databinding + 'Me.DataGridView1.DataBindings(0).DataSourceUpdateMode = DataSourceUpdateMode.Never + 'Me.DataGridView1.DataBindings.Add(New Binding(binding) + 'set CurrentCulture for MaskedTextBox Me.MaskedTextBox_JumpDate.Culture = Globalization.CultureInfo.CurrentCulture Me.MaskedTextBox_JumpDate.FormatProvider = Globalization.CultureInfo.CurrentCulture @@ -78,37 +90,80 @@ Friend Class ValuesWindow ''' the new List of TimeSeries Public Overloads Sub Update(ByRef seriesList As List(Of TimeSeries)) + Me.tsList = seriesList + + If Me.Visible Then + Call Me.loadDataTable() + End If + + End Sub + + ''' + ''' Loads records when the form becomes visible + ''' + ''' + ''' + Private Sub TimeSeriesValuesDialog_VisibleChanged(sender As Object, e As EventArgs) Handles MyBase.VisibleChanged + If Me.Visible Then + + 'load data in the datatable + Call Me.loadDataTable() + + 'load first rows + startIndex = 0 + populateRows() + End If + End Sub + + ''' + ''' Loads the current time series list into the DataTable + ''' + Private Sub loadDataTable() + Dim table As DataTable = Me.dataset.Tables("data") + Me.DataGridView1.SuspendLayout() + Me.databinding.SuspendBinding() + Me.dataview.RowStateFilter = DataViewRowState.None + Me.dataview.RowFilter = String.Empty + table.Clear() table.Columns.Clear() + Dim nHeaderColumns As Integer = 2 + table.Columns.Add("index", GetType(Long)) table.Columns.Add("Timestamp", GetType(DateTime)) - For Each ts As TimeSeries In seriesList + Dim nColumns As Integer = Me.tsList.Count + nHeaderColumns + For Each ts As TimeSeries In Me.tsList table.Columns.Add(ts.Title, GetType(Double)) Next 'collect unique timestamps Dim unique_timestamps As New HashSet(Of DateTime) - For Each ts As TimeSeries In seriesList + For Each ts As TimeSeries In Me.tsList unique_timestamps.UnionWith(New HashSet(Of DateTime)(ts.Dates)) Next + 'sort timestamps Dim timestamps As List(Of DateTime) = unique_timestamps.ToList() timestamps.Sort() 'add a row for each timestamp table.BeginLoadData() + Dim index As Long = 0 Dim cellvalues() As Object For Each t As DateTime In timestamps - ReDim cellvalues(seriesList.Count) + ReDim cellvalues(nColumns - 1) + + 'first column is index + cellvalues(0) = index - 'first value is timestamp - cellvalues(0) = t + 'second column is timestamp + cellvalues(1) = t 'add a value for each series - Dim icol As Integer = 1 - For Each ts As TimeSeries In seriesList + Dim icol As Integer = nHeaderColumns + For Each ts As TimeSeries In Me.tsList If ts.Dates.Contains(t) Then cellvalues(icol) = ts.Nodes(t) Else @@ -118,48 +173,29 @@ Friend Class ValuesWindow Next table.Rows.Add(cellvalues) + + index += 1 Next table.EndLoadData() - 'Reset DatagridView - Me.DataGridView1.Rows.Clear() - Me.DataGridView1.Columns.Clear() - Dim colindex As Integer = 0 - For Each col As DataColumn In table.Columns - Me.DataGridView1.Columns.Add(col.ColumnName, col.ColumnName) - If colindex = 0 Then - 'freeze timestamp column - Me.DataGridView1.Columns(colindex).Frozen = True - End If - colindex += 1 - Next + Me.dataview.RowFilter = "index >= 0 and index < 100" + Me.dataview.RowStateFilter = DataViewRowState.CurrentRows + Me.databinding.ResumeBinding() + Me.DataGridView1.ResumeLayout() 'set max startIndex - NumericUpDown_StartRecord.Maximum = table.Rows.Count + NumericUpDown_StartRecord.Maximum = Me.dataset.Tables("data").Rows.Count 'set first date as initial value for jump date - If timestamps.Count > 0 Then - Dim firstDate As DateTime = timestamps.First + If Me.dataset.Tables("data").Rows.Count > 0 Then + Dim firstDate As DateTime = Me.dataset.Tables("data").Rows(0)(1) MaskedTextBox_JumpDate.Text = firstDate.ToString() End If - If Me.Visible Then - populateRows() - End If - - End Sub + Me.DataGridView1.Columns(0).Visible = False + Me.DataGridView1.Columns(0).Frozen = True + Me.DataGridView1.Columns(1).Frozen = True - ''' - ''' Loads records when the form becomes visible - ''' - ''' - ''' - Private Sub TimeSeriesValuesDialog_VisibleChanged(sender As Object, e As EventArgs) Handles MyBase.VisibleChanged - If Me.Visible Then - 'load first rows - startIndex = 0 - populateRows() - End If End Sub ''' @@ -167,29 +203,17 @@ Friend Class ValuesWindow ''' Private Sub populateRows() - Dim rows() As DataGridViewRow - Dim recordIndex, numRows As Integer - Dim table As DataTable = Me.dataset.Tables("data") - Me.Cursor = Cursors.WaitCursor + Me.DataGridView1.SuspendLayout() + + Dim numRows, endIndex As Integer + Dim table As DataTable = Me.dataset.Tables("data") numRows = Math.Min(maxRows, table.Rows.Count - startIndex) + endIndex = startIndex + numRows - 'Add new rows to datagridview - Me.DataGridView1.SuspendLayout() - Me.DataGridView1.Rows.Clear() - If numRows > 0 Then - ReDim rows(numRows - 1) - For i As Integer = 0 To numRows - 1 - recordIndex = startIndex + i - rows(i) = New DataGridViewRow() - rows(i).CreateCells(DataGridView1, table.Rows(recordIndex).ItemArray) - rows(i).HeaderCell.Value = (recordIndex + 1).ToString() - Next - Me.DataGridView1.Rows.AddRange(rows) - End If - Me.DataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells) - Me.DataGridView1.ResumeLayout() + 'update filter + dataview.RowFilter = $"index >= {startIndex} and index < {endIndex}" 'Update label Dim startRecord As Integer @@ -200,6 +224,7 @@ Friend Class ValuesWindow End If Me.Label_DisplayCount.Text = $"Displaying records {startRecord} to {startRecord + numRows - 1} of {table.Rows.Count}" + Me.DataGridView1.ResumeLayout() Me.Cursor = Cursors.Default End Sub @@ -218,7 +243,7 @@ Friend Class ValuesWindow ''' ''' ''' - Private Sub Button_previous_Click(sender As Object, e As EventArgs) Handles Button_previous.Click, Button_first.Click + Private Sub Button_previous_Click(sender As Object, e As EventArgs) Handles Button_previous.Click startIndex = Math.Max(0, startIndex - maxRows) End Sub @@ -263,7 +288,7 @@ Friend Class ValuesWindow Dim selectedRows As DataGridViewSelectedRowCollection = DataGridView1.SelectedRows() Dim timestamps As New List(Of DateTime) For Each row As DataGridViewRow In selectedRows - timestamps.Add(row.Cells(0).Value) + timestamps.Add(row.Cells(1).Value) Next RaiseEvent SelectedRowsChanged(timestamps) End If @@ -326,10 +351,10 @@ Friend Class ValuesWindow 'search for selected date in dataset and set startIndex accordingly Dim rowIndex As Integer = 0 For Each row As DataRow In table.Rows - If row.ItemArray(0) = selectedDate Then + If row.ItemArray(1) = selectedDate Then startIndex = rowIndex Exit For - ElseIf row.ItemArray(0) > selectedDate Then + ElseIf row.ItemArray(1) > selectedDate Then startIndex = rowIndex - 1 Exit For End If From 4784c331cd22d30e2220c88be83ef5ef794aee5a Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 09:52:20 +0100 Subject: [PATCH 02/13] store column indices as constants --- source/Views/ValuesWindow.vb | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 3efc108b..2dace847 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -19,6 +19,10 @@ Imports System.Windows.Forms Friend Class ValuesWindow Implements IView + Const colIndex As Integer = 0 + Const colDateTime As Integer = 1 + Const nHeaderColumns As Integer = 2 + Private isInitializing As Boolean Private tsList As List(Of TimeSeries) Private dataset As DataSet @@ -129,7 +133,6 @@ Friend Class ValuesWindow table.Clear() table.Columns.Clear() - Dim nHeaderColumns As Integer = 2 table.Columns.Add("index", GetType(Long)) table.Columns.Add("Timestamp", GetType(DateTime)) Dim nColumns As Integer = Me.tsList.Count + nHeaderColumns @@ -155,11 +158,11 @@ Friend Class ValuesWindow ReDim cellvalues(nColumns - 1) - 'first column is index - cellvalues(0) = index + 'index column + cellvalues(colIndex) = index - 'second column is timestamp - cellvalues(1) = t + 'timestamp column + cellvalues(colDateTime) = t 'add a value for each series Dim icol As Integer = nHeaderColumns @@ -192,9 +195,9 @@ Friend Class ValuesWindow MaskedTextBox_JumpDate.Text = firstDate.ToString() End If - Me.DataGridView1.Columns(0).Visible = False - Me.DataGridView1.Columns(0).Frozen = True - Me.DataGridView1.Columns(1).Frozen = True + Me.DataGridView1.Columns(colIndex).Visible = False + Me.DataGridView1.Columns(colIndex).Frozen = True + Me.DataGridView1.Columns(colDateTime).Frozen = True End Sub @@ -288,7 +291,7 @@ Friend Class ValuesWindow Dim selectedRows As DataGridViewSelectedRowCollection = DataGridView1.SelectedRows() Dim timestamps As New List(Of DateTime) For Each row As DataGridViewRow In selectedRows - timestamps.Add(row.Cells(1).Value) + timestamps.Add(row.Cells(colDateTime).Value) Next RaiseEvent SelectedRowsChanged(timestamps) End If @@ -351,10 +354,10 @@ Friend Class ValuesWindow 'search for selected date in dataset and set startIndex accordingly Dim rowIndex As Integer = 0 For Each row As DataRow In table.Rows - If row.ItemArray(1) = selectedDate Then + If row.ItemArray(colDateTime) = selectedDate Then startIndex = rowIndex Exit For - ElseIf row.ItemArray(1) > selectedDate Then + ElseIf row.ItemArray(colDateTime) > selectedDate Then startIndex = rowIndex - 1 Exit For End If From 49857f7ffd42d0274a8dd412b400a6b6a57bbe29 Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 09:57:28 +0100 Subject: [PATCH 03/13] refactor to use property --- source/Views/ValuesWindow.vb | 53 +++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 2dace847..2080f0de 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -35,6 +35,19 @@ Friend Class ValuesWindow _controller = controller End Sub + Private ReadOnly Property dataTable As DataTable + Get + Return Me.dataset.Tables("data") + End Get + End Property + + Private ReadOnly Property nRows As Integer + Get + Return Me.dataTable.Rows.Count + End Get + End Property + + ''' ''' The starting index of records to display in the datagridview ''' @@ -124,20 +137,18 @@ Friend Class ValuesWindow ''' Private Sub loadDataTable() - Dim table As DataTable = Me.dataset.Tables("data") - Me.DataGridView1.SuspendLayout() Me.databinding.SuspendBinding() Me.dataview.RowStateFilter = DataViewRowState.None Me.dataview.RowFilter = String.Empty - table.Clear() - table.Columns.Clear() - table.Columns.Add("index", GetType(Long)) - table.Columns.Add("Timestamp", GetType(DateTime)) + Me.dataTable.Clear() + Me.dataTable.Columns.Clear() + Me.dataTable.Columns.Add("index", GetType(Long)) + Me.dataTable.Columns.Add("Timestamp", GetType(DateTime)) Dim nColumns As Integer = Me.tsList.Count + nHeaderColumns For Each ts As TimeSeries In Me.tsList - table.Columns.Add(ts.Title, GetType(Double)) + Me.dataTable.Columns.Add(ts.Title, GetType(Double)) Next 'collect unique timestamps @@ -151,7 +162,7 @@ Friend Class ValuesWindow timestamps.Sort() 'add a row for each timestamp - table.BeginLoadData() + Me.dataTable.BeginLoadData() Dim index As Long = 0 Dim cellvalues() As Object For Each t As DateTime In timestamps @@ -175,11 +186,11 @@ Friend Class ValuesWindow icol += 1 Next - table.Rows.Add(cellvalues) + Me.dataTable.Rows.Add(cellvalues) index += 1 Next - table.EndLoadData() + Me.dataTable.EndLoadData() Me.dataview.RowFilter = "index >= 0 and index < 100" Me.dataview.RowStateFilter = DataViewRowState.CurrentRows @@ -187,11 +198,11 @@ Friend Class ValuesWindow Me.DataGridView1.ResumeLayout() 'set max startIndex - NumericUpDown_StartRecord.Maximum = Me.dataset.Tables("data").Rows.Count + NumericUpDown_StartRecord.Maximum = Me.nRows 'set first date as initial value for jump date - If Me.dataset.Tables("data").Rows.Count > 0 Then - Dim firstDate As DateTime = Me.dataset.Tables("data").Rows(0)(1) + If Me.nRows > 0 Then + Dim firstDate As DateTime = Me.dataTable.Rows(0)(1) MaskedTextBox_JumpDate.Text = firstDate.ToString() End If @@ -210,9 +221,8 @@ Friend Class ValuesWindow Me.DataGridView1.SuspendLayout() Dim numRows, endIndex As Integer - Dim table As DataTable = Me.dataset.Tables("data") - numRows = Math.Min(maxRows, table.Rows.Count - startIndex) + numRows = Math.Min(maxRows, Me.nRows - startIndex) endIndex = startIndex + numRows 'update filter @@ -220,12 +230,12 @@ Friend Class ValuesWindow 'Update label Dim startRecord As Integer - If table.Rows.Count = 0 Then + If Me.nRows = 0 Then startRecord = 0 Else startRecord = startIndex + 1 End If - Me.Label_DisplayCount.Text = $"Displaying records {startRecord} to {startRecord + numRows - 1} of {table.Rows.Count}" + Me.Label_DisplayCount.Text = $"Displaying records {startRecord} to {startRecord + numRows - 1} of {Me.nRows}" Me.DataGridView1.ResumeLayout() Me.Cursor = Cursors.Default @@ -256,7 +266,7 @@ Friend Class ValuesWindow ''' ''' Private Sub Button_next_Click(sender As Object, e As EventArgs) Handles Button_next.Click - startIndex = Math.Min(Me.dataset.Tables("data").Rows.Count - 1, startIndex + maxRows) + startIndex = Math.Min(Me.nRows - 1, startIndex + maxRows) End Sub ''' @@ -265,7 +275,7 @@ Friend Class ValuesWindow ''' ''' Private Sub Button_last_Click(sender As Object, e As EventArgs) Handles Button_last.Click - startIndex = Math.Max(0, Me.dataset.Tables("data").Rows.Count - maxRows) + startIndex = Math.Max(0, Me.nRows - maxRows) End Sub ''' @@ -348,12 +358,11 @@ Friend Class ValuesWindow Private Sub MaskedTextBox_JumpDate_ValueChanged(sender As Object, e As EventArgs) Handles MaskedTextBox_JumpDate.Validated, Button_Jump.Click Me.Cursor = Cursors.WaitCursor Dim selectedDate As DateTime = CType(Me.MaskedTextBox_JumpDate.Text, DateTime) - Dim table As DataTable = Me.dataset.Tables("data") 'use last record as default (will be used if the selected date is later than the last date of dataset) - startIndex = table.Rows.Count - 1 + startIndex = Me.nRows - 1 'search for selected date in dataset and set startIndex accordingly Dim rowIndex As Integer = 0 - For Each row As DataRow In table.Rows + For Each row As DataRow In Me.dataTable.Rows If row.ItemArray(colDateTime) = selectedDate Then startIndex = rowIndex Exit For From 5073008eaf99ba051da9149b0ac4e1bf9be2737c Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 10:07:48 +0100 Subject: [PATCH 04/13] renamed method, cleaned up comments --- source/Views/ValuesWindow.vb | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 2080f0de..68b67e34 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -89,8 +89,6 @@ Friend Class ValuesWindow .DataSource = Me.dataview } Me.DataGridView1.DataSource = Me.databinding - 'Me.DataGridView1.DataBindings(0).DataSourceUpdateMode = DataSourceUpdateMode.Never - 'Me.DataGridView1.DataBindings.Add(New Binding(binding) 'set CurrentCulture for MaskedTextBox Me.MaskedTextBox_JumpDate.Culture = Globalization.CultureInfo.CurrentCulture @@ -122,13 +120,12 @@ Friend Class ValuesWindow ''' Private Sub TimeSeriesValuesDialog_VisibleChanged(sender As Object, e As EventArgs) Handles MyBase.VisibleChanged If Me.Visible Then - 'load data in the datatable Call Me.loadDataTable() - 'load first rows + 'display first rows startIndex = 0 - populateRows() + updateDataViewFilter() End If End Sub @@ -213,9 +210,9 @@ Friend Class ValuesWindow End Sub ''' - ''' Populates the datagridview with data starting from the currently set startIndex + ''' Updates the DataViewFilter to show rows starting from the currently set startIndex ''' - Private Sub populateRows() + Private Sub updateDataViewFilter() Me.Cursor = Cursors.WaitCursor Me.DataGridView1.SuspendLayout() @@ -285,7 +282,7 @@ Friend Class ValuesWindow ''' Private Sub NumericUpDown_StartIndex_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown_StartRecord.ValueChanged If Not Me.isInitializing Then - populateRows() + updateDataViewFilter() End If End Sub @@ -372,8 +369,8 @@ Friend Class ValuesWindow End If rowIndex += 1 Next - 'populate datagridview - populateRows() + 'update data view filter + updateDataViewFilter() Me.Cursor = Cursors.Default End Sub From 56bafc22c4ef0a695f318ec0bf142810d512cb37 Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 10:25:00 +0100 Subject: [PATCH 05/13] use Me --- source/Views/ValuesWindow.vb | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 68b67e34..8fafc6d5 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -124,7 +124,7 @@ Friend Class ValuesWindow Call Me.loadDataTable() 'display first rows - startIndex = 0 + Me.startIndex = 0 updateDataViewFilter() End If End Sub @@ -199,7 +199,7 @@ Friend Class ValuesWindow 'set first date as initial value for jump date If Me.nRows > 0 Then - Dim firstDate As DateTime = Me.dataTable.Rows(0)(1) + Dim firstDate As DateTime = Me.dataTable.Rows(0)(colDateTime) MaskedTextBox_JumpDate.Text = firstDate.ToString() End If @@ -219,18 +219,18 @@ Friend Class ValuesWindow Dim numRows, endIndex As Integer - numRows = Math.Min(maxRows, Me.nRows - startIndex) - endIndex = startIndex + numRows + numRows = Math.Min(maxRows, Me.nRows - Me.startIndex) + endIndex = Me.startIndex + numRows 'update filter - dataview.RowFilter = $"index >= {startIndex} and index < {endIndex}" + dataview.RowFilter = $"index >= {Me.startIndex} and index < {endIndex}" 'Update label Dim startRecord As Integer If Me.nRows = 0 Then startRecord = 0 Else - startRecord = startIndex + 1 + startRecord = Me.startIndex + 1 End If Me.Label_DisplayCount.Text = $"Displaying records {startRecord} to {startRecord + numRows - 1} of {Me.nRows}" @@ -245,7 +245,7 @@ Friend Class ValuesWindow ''' ''' Private Sub Button_first_Click(sender As Object, e As EventArgs) Handles Button_first.Click - startIndex = 0 + Me.startIndex = 0 End Sub ''' @@ -254,7 +254,7 @@ Friend Class ValuesWindow ''' ''' Private Sub Button_previous_Click(sender As Object, e As EventArgs) Handles Button_previous.Click - startIndex = Math.Max(0, startIndex - maxRows) + Me.startIndex = Math.Max(0, Me.startIndex - maxRows) End Sub ''' @@ -263,7 +263,7 @@ Friend Class ValuesWindow ''' ''' Private Sub Button_next_Click(sender As Object, e As EventArgs) Handles Button_next.Click - startIndex = Math.Min(Me.nRows - 1, startIndex + maxRows) + Me.startIndex = Math.Min(Me.nRows - 1, Me.startIndex + maxRows) End Sub ''' @@ -272,7 +272,7 @@ Friend Class ValuesWindow ''' ''' Private Sub Button_last_Click(sender As Object, e As EventArgs) Handles Button_last.Click - startIndex = Math.Max(0, Me.nRows - maxRows) + Me.startIndex = Math.Max(0, Me.nRows - maxRows) End Sub ''' @@ -352,24 +352,26 @@ Friend Class ValuesWindow ''' ''' ''' - Private Sub MaskedTextBox_JumpDate_ValueChanged(sender As Object, e As EventArgs) Handles MaskedTextBox_JumpDate.Validated, Button_Jump.Click + Private Sub MaskedTextBox_JumpDate_ValueChanged(sender As Object, e As EventArgs) Handles Button_Jump.Click Me.Cursor = Cursors.WaitCursor + Dim index As Integer Dim selectedDate As DateTime = CType(Me.MaskedTextBox_JumpDate.Text, DateTime) 'use last record as default (will be used if the selected date is later than the last date of dataset) - startIndex = Me.nRows - 1 + index = Me.nRows - 1 'search for selected date in dataset and set startIndex accordingly Dim rowIndex As Integer = 0 For Each row As DataRow In Me.dataTable.Rows If row.ItemArray(colDateTime) = selectedDate Then - startIndex = rowIndex + index = rowIndex Exit For ElseIf row.ItemArray(colDateTime) > selectedDate Then - startIndex = rowIndex - 1 + index = rowIndex - 1 Exit For End If rowIndex += 1 Next 'update data view filter + Me.startIndex = index updateDataViewFilter() Me.Cursor = Cursors.Default End Sub From c625ee8af8f6e4c748bef31f4702db038b23323a Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 10:36:44 +0100 Subject: [PATCH 06/13] reset start index when datatable is reloaded --- source/Views/ValuesWindow.vb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 8fafc6d5..33f00bfe 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -203,6 +203,9 @@ Friend Class ValuesWindow MaskedTextBox_JumpDate.Text = firstDate.ToString() End If + 'reset start index + Me.startIndex = 0 + Me.DataGridView1.Columns(colIndex).Visible = False Me.DataGridView1.Columns(colIndex).Frozen = True Me.DataGridView1.Columns(colDateTime).Frozen = True From d95f7bf33a9e43afdbdc6de95879b453624d6849 Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 10:42:37 +0100 Subject: [PATCH 07/13] only reset jump date to first date on first window display --- source/Views/ValuesWindow.vb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 33f00bfe..34cb4871 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -123,9 +123,15 @@ Friend Class ValuesWindow 'load data in the datatable Call Me.loadDataTable() + 'set first date as initial value for jump date + If Me.nRows > 0 Then + Dim firstDate As DateTime = Me.dataTable.Rows(0)(colDateTime) + MaskedTextBox_JumpDate.Text = firstDate.ToString() + End If + 'display first rows Me.startIndex = 0 - updateDataViewFilter() + Call Me.updateDataViewFilter() End If End Sub @@ -197,12 +203,6 @@ Friend Class ValuesWindow 'set max startIndex NumericUpDown_StartRecord.Maximum = Me.nRows - 'set first date as initial value for jump date - If Me.nRows > 0 Then - Dim firstDate As DateTime = Me.dataTable.Rows(0)(colDateTime) - MaskedTextBox_JumpDate.Text = firstDate.ToString() - End If - 'reset start index Me.startIndex = 0 @@ -285,7 +285,7 @@ Friend Class ValuesWindow ''' Private Sub NumericUpDown_StartIndex_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown_StartRecord.ValueChanged If Not Me.isInitializing Then - updateDataViewFilter() + Call Me.updateDataViewFilter() End If End Sub @@ -375,7 +375,7 @@ Friend Class ValuesWindow Next 'update data view filter Me.startIndex = index - updateDataViewFilter() + Call Me.updateDataViewFilter() Me.Cursor = Cursors.Default End Sub From 94194c22f3eda8faab8dd900a43cdd06b6c874cb Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:20:19 +0100 Subject: [PATCH 08/13] remember whether jump date was set and set startindex accordingly when data table is updated --- source/Views/ValuesWindow.vb | 55 +++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 34cb4871..3e38ef02 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -28,6 +28,7 @@ Friend Class ValuesWindow Private dataset As DataSet Private dataview As DataView Private databinding As BindingSource + Private IsJumpDateSet As Boolean = False Private _controller As ValuesController @@ -122,16 +123,13 @@ Friend Class ValuesWindow If Me.Visible Then 'load data in the datatable Call Me.loadDataTable() - - 'set first date as initial value for jump date + 'reset start index and jump date + Me.startIndex = 0 + Me.IsJumpDateSet = False If Me.nRows > 0 Then Dim firstDate As DateTime = Me.dataTable.Rows(0)(colDateTime) MaskedTextBox_JumpDate.Text = firstDate.ToString() End If - - 'display first rows - Me.startIndex = 0 - Call Me.updateDataViewFilter() End If End Sub @@ -203,8 +201,21 @@ Friend Class ValuesWindow 'set max startIndex NumericUpDown_StartRecord.Maximum = Me.nRows - 'reset start index - Me.startIndex = 0 + 'determine start index + Dim jumpDate As DateTime + Dim isDate As Boolean = DateTime.TryParse(Me.MaskedTextBox_JumpDate.Text, jumpDate) + If isDate And Me.IsJumpDateSet Then + 'set start index to correspond to currently set jump date + Me.startIndex = Me.getStartIndexForDate(jumpDate) + Call Me.updateDataViewFilter() + Else + 'set start index to 0 and jump date to first date + Me.startIndex = 0 + If Me.nRows > 0 Then + Dim firstDate As DateTime = Me.dataTable.Rows(0)(colDateTime) + MaskedTextBox_JumpDate.Text = firstDate.ToString() + End If + End If Me.DataGridView1.Columns(colIndex).Visible = False Me.DataGridView1.Columns(colIndex).Frozen = True @@ -357,27 +368,37 @@ Friend Class ValuesWindow ''' Private Sub MaskedTextBox_JumpDate_ValueChanged(sender As Object, e As EventArgs) Handles Button_Jump.Click Me.Cursor = Cursors.WaitCursor + Dim jumpDate As DateTime = CType(Me.MaskedTextBox_JumpDate.Text, DateTime) + Me.IsJumpDateSet = True + 'update data view filter + Me.startIndex = Me.getStartIndexForDate(jumpDate) + Call Me.updateDataViewFilter() + Me.Cursor = Cursors.Default + End Sub + + ''' + ''' Returns the start index corresponding to the given date + ''' + ''' Date + ''' Index + Private Function getStartIndexForDate(timestamp As DateTime) As Integer Dim index As Integer - Dim selectedDate As DateTime = CType(Me.MaskedTextBox_JumpDate.Text, DateTime) - 'use last record as default (will be used if the selected date is later than the last date of dataset) + 'use last record as default (will be used if the timestamp is later than the last timestamp of the dataset) index = Me.nRows - 1 'search for selected date in dataset and set startIndex accordingly Dim rowIndex As Integer = 0 For Each row As DataRow In Me.dataTable.Rows - If row.ItemArray(colDateTime) = selectedDate Then + If row.ItemArray(colDateTime) = timestamp Then index = rowIndex Exit For - ElseIf row.ItemArray(colDateTime) > selectedDate Then + ElseIf row.ItemArray(colDateTime) > timestamp Then index = rowIndex - 1 Exit For End If rowIndex += 1 Next - 'update data view filter - Me.startIndex = index - Call Me.updateDataViewFilter() - Me.Cursor = Cursors.Default - End Sub + Return index + End Function Private Sub TimeSeriesValuesDialog_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing 'stop highlighting From 05a51c1a0c5426948dbaaa6f5f6e7d226fd4be10 Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:27:39 +0100 Subject: [PATCH 09/13] update dataview on window show --- source/Views/ValuesWindow.vb | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 3e38ef02..323aa7e3 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -130,6 +130,7 @@ Friend Class ValuesWindow Dim firstDate As DateTime = Me.dataTable.Rows(0)(colDateTime) MaskedTextBox_JumpDate.Text = firstDate.ToString() End If + Call Me.updateDataViewFilter() End If End Sub From f152aabed73bde767efcad039df7c3196435a7cc Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:30:31 +0100 Subject: [PATCH 10/13] use constant --- source/Views/ValuesWindow.vb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index 323aa7e3..b8fc990f 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -23,6 +23,11 @@ Friend Class ValuesWindow Const colDateTime As Integer = 1 Const nHeaderColumns As Integer = 2 + ''' + ''' The maximum number of rows to display in the datagridview at a time + ''' + Private Const maxRows As Integer = 100 + Private isInitializing As Boolean Private tsList As List(Of TimeSeries) Private dataset As DataSet @@ -65,11 +70,6 @@ Friend Class ValuesWindow End Set End Property - ''' - ''' The maximum number of rows to display in the datagridview at a time - ''' - Private Const maxRows As Integer = 100 - Public Event SelectedRowsChanged(timestamps As List(Of DateTime)) Public Sub New() @@ -194,7 +194,7 @@ Friend Class ValuesWindow Next Me.dataTable.EndLoadData() - Me.dataview.RowFilter = "index >= 0 and index < 100" + Me.dataview.RowFilter = $"index >= 0 and index < {maxRows}" Me.dataview.RowStateFilter = DataViewRowState.CurrentRows Me.databinding.ResumeBinding() Me.DataGridView1.ResumeLayout() From 5ac309dafe4288558a66a2e3016874c54e2bb23b Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:36:59 +0100 Subject: [PATCH 11/13] rename and comments --- source/Views/ValuesWindow.vb | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/source/Views/ValuesWindow.vb b/source/Views/ValuesWindow.vb index b8fc990f..7aa1b938 100644 --- a/source/Views/ValuesWindow.vb +++ b/source/Views/ValuesWindow.vb @@ -41,19 +41,26 @@ Friend Class ValuesWindow _controller = controller End Sub + ''' + ''' The datatable containing all the data + ''' + ''' Private ReadOnly Property dataTable As DataTable Get Return Me.dataset.Tables("data") End Get End Property + ''' + ''' The number of rows currently contained in the datatable + ''' + ''' Private ReadOnly Property nRows As Integer Get Return Me.dataTable.Rows.Count End Get End Property - ''' ''' The starting index of records to display in the datagridview ''' @@ -70,6 +77,10 @@ Friend Class ValuesWindow End Set End Property + ''' + ''' Is raised when the selected rows changes + ''' + ''' List of selected timestamps Public Event SelectedRowsChanged(timestamps As List(Of DateTime)) Public Sub New() @@ -109,7 +120,7 @@ Friend Class ValuesWindow Me.tsList = seriesList If Me.Visible Then - Call Me.loadDataTable() + Call Me.UpdateDataTable() End If End Sub @@ -121,8 +132,8 @@ Friend Class ValuesWindow ''' Private Sub TimeSeriesValuesDialog_VisibleChanged(sender As Object, e As EventArgs) Handles MyBase.VisibleChanged If Me.Visible Then - 'load data in the datatable - Call Me.loadDataTable() + 'update the datatable + Call Me.UpdateDataTable() 'reset start index and jump date Me.startIndex = 0 Me.IsJumpDateSet = False @@ -135,9 +146,9 @@ Friend Class ValuesWindow End Sub ''' - ''' Loads the current time series list into the DataTable + ''' Updates the DataTable using the current list of time series ''' - Private Sub loadDataTable() + Private Sub UpdateDataTable() Me.DataGridView1.SuspendLayout() Me.databinding.SuspendBinding() From 345164771077e5c0470d5ce16d21adf9ac3306a9 Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:58:50 +0100 Subject: [PATCH 12/13] only update view on first show --- source/Controllers/ValuesController.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Controllers/ValuesController.vb b/source/Controllers/ValuesController.vb index 2369bfbe..a4986cf7 100644 --- a/source/Controllers/ValuesController.vb +++ b/source/Controllers/ValuesController.vb @@ -47,8 +47,8 @@ Friend Class ValuesController Public Overrides Sub ShowView() If IsNothing(_view) Then _view = New ValuesWindow() + View.Update(_model.TimeSeries.ToList) End If - View.Update(_model.TimeSeries.ToList) View.WindowState = FormWindowState.Normal View.Show() View.BringToFront() From 7970d45a351f94cb4bf88e26ede1e1035aae3feb Mon Sep 17 00:00:00 2001 From: jamaa <90166+jamaa@users.noreply.github.com> Date: Sun, 12 Nov 2023 12:01:18 +0100 Subject: [PATCH 13/13] update changelog --- source/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/CHANGELOG.md b/source/CHANGELOG.md index beb25d23..b93934dc 100644 --- a/source/CHANGELOG.md +++ b/source/CHANGELOG.md @@ -12,6 +12,9 @@ NEW: * When saving to WVP, file paths can now optionally be saved as relative * WVP files are now always read and written using UTF-8 encoding +FIXED: +* Improved performance and usability of Time Series Values window + CHANGED: * Upgrade TeeChart to v4.2023.4.18