VB.net Redraw / Refresh / recalculate Chart - vb.net

I guess there's tons of answers, but i have only found answers regarding the data update, not the chart itself.
In my case i have a chart that updates every X minutes. When the program starts, it looks in a file for some values. Lets say there's only one one value (one column in this case), and this value is 20. Then it shows it nice with 30 as maximum.
When it refresh, i do something like this
TheDiagram.Series.Clear()
Dim Serie_Value As New Series
With Serie_Value
.Name = "MySerie"
.ChartType = SeriesChartType.StackedColumn
.Color = Color.Green
With .Points
.AddXY("MyName", theValueFromFile)
End With
End With
TheDiagram.Series.Add(Serie_Value)
In this case, we say that the value now is 60, then the y-axis is still on 30 as max so that I can't see the end (top) of the column.
How can I tell the chart/chartarea to "redraw yourself like you were rendered the first time"?

To reset the auto scale just use this after loading the points into the chart.
Chart1.ResetAutoValues()

Have you tried auto-scaling the y-axis?
' Auto axis scale
Chart1.ChartAreas("ChartArea1").AxisY.Minimum = [Double].NaN
Chart1.ChartAreas("ChartArea1").AxisY.Maximum = [Double].NaN
You should set those every time the chart refreshes, the axis should adjust automatically then.

Available since .NET 4.0: Chart1.ChartAreas[0].RecalculateAxesScale();

Related

Applying style changes to individual cells in DataGridView is very slow

I have a DataGridView (DGV) that I'm populating manually (not bound to a datasource). It's relatively small (12 columns x 62 rows). When my form loads, it populates each cell with data from various sources, and applies style changes to some of the cells, such as fore color, background color, and possibly font change.
Everything is going great except for the style changes. I did some tests using Stopwatches, and the formatting is taking roughly 2X longer than all of the processing that goes into populating the form. My computations are fairly intensive, whereas I would think applying formatting would be almost instantaneous, so I'm baffled why applying some style changes is taking twice as long as my intense computations.
I've already taken some measures to reduce the time quite a bit, such as turning on double-buffering as well as suspending drawing for my DGV before my formatting begins and resuming it after. These helped a lot, and also eliminated the flicker that was happening as each cell of my DGV was repainted. As far as I can tell, doing these two things helped combine the actual painting of the style changes into a single paint operation. So a rough outline of the loading of my form goes like this:
Form load begin
"SuspendDrawing" for DGV
Populate DGV with data
Apply style changes to each cell
"ResumeDrawing" for DGV and Refresh (Redraw) DGV.
To clarify, Step 4 is made up only of lines like the following:
myCell.Style = New DataGridViewStyle()
myCell.Style.BackColor = ...
myCell.Style.ForeColor = ...
myCell.Style.Font = New Font()
In all those steps, it's Step 4 that takes the most time. Even Step 5 is nearly instantaneous. This doesn't make sense to me. Drawing is suspended when Step 4 takes place, so there should be no graphics computations or painting taking place. It should purely be storing those Style changes for each cell.
So, why is applying cell style changes so slow, and what can I do to speed it up other than what I already have?
Update 2/5/20
I've been asked to provide reproducible code. I'll need to take some time to put together a MWE. In the meantime, hopefully this will help: after populating my table (step 3 above), I apply cell styles in Step 4 something like this:
For Each row As DataGridViewRow In myDGV.Rows
For Each cell As DataGridViewCell In row.Cells
Select Case [somecondition]
Case X
cell.Style = New DataGridViewStyle()
cell.Style.BackColor = Colors.White
cell.Style.ForeColor = Colors.Black
cell.Style.Font = New Font(DefaultFont, FontStyle.Italic)
Case Y
[similar]
Case ...
End Select
Next
Next
I followed jmcilhinney's advice and created and configured a Style variable for each iteration and assigned that to the cell, rather than modifying each live cell's Style multiple times. This made the formatting about 140X faster, reducing it from 1.4 seconds to 0.01 seconds. My resulting code looked something like this:
For Each row As DataGridViewRow In myDGV.Rows
For Each cell As DataGridViewCell In row.Cells
Select Case [somecondition]
Case X
Dim styleVar as New DataGridViewStyle()
styleVar.BackColor = Colors.White
styleVar.ForeColor = Colors.Black
styleVar.Font = New Font(DefaultFont, FontStyle.Italic)
cell.Style = styleVar
Case Y
[similar]
Case ...
End Select
Next
Next

problem with fitting datagridview height according to the content

I have a datagridview whose styling is kept as follows
dgvCreatinine.AutoGenerateColumns = False
dgvCreatinine.AutoSize = False
dgvCreatinine.AutoResizeRows()
dgvCreatinine.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill
dgvCreatinine.AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders)
dgvCreatinine.DataSource = dtTemp
It is appearing as shown in the attached image
As you can see the gridview is not resizing to the content along row wise. Could someone tell me how this can be accomplished? Thanks in advance.
You can just set the height of the entire control using this formula
DataGridViewHeight = HeaderHeight + NumberOfRows * RowHeight
Code:
dgvCreatinine.Height =
dgvCreatinine.ColumnHeadersHeight _
+ dgvCreatinine.Rows.OfType(Of DataGridViewRow).First().Height * dgvCreatinine.Rows.Count()
This works, but could use some tweaking. For example, there may be a better way to get the row height. And you may also need to add a pixel or two depending on borders. Also, if you have an underlying DataSource, you could get the rows count from it.
That code should be called whenever a row is added or removed, or DataBindings are updated etc.

Completely resize DataGridView in VB.NET

I am having issues resizing a DataGridView in a VB.NET application. The DataGridView is not bound to a data source, as all data is entered into it manually.
It is currently docked in a TableLayoutPanel, set to Fill, and I would expect it to automatically resize to fit its assigned cell, but it seems to have a minimum size, at which I can not shrink it any further. This is a problem because the tablet PC I am deploying to has a much smaller resolution, so the Windows must scale properly. The TableLayoutPanels are keeping everything in the correct position, but it is crucial that my grids scale as well so that the end user can see the bottom scroll bar and all the records in the table.
This problem is pretty much the same as the one mentioned here.
If you go to AlternatingRowsDefaultCellStyle in the properties window of the datagridviewer there is Padding feature that defaults to 0,0,0,0 which represents each direction. Perhaps if you reduce the padding it will autosize up instead of being limited on the upper end moving down.
Use AutoSizeMode and FillWeight properties of columns in your datagridview
'Column 1
Dim columnindex As Int32 = Me.DataGridView1.Columns.Add("One", "One")
With Me.DataGridView1.Columns(columnindex)
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
.FillWeight = 80 'This can be used as percent value for column width
End With
'Column 2
columnindex = Me.DataGridView1.Columns.Add("Two", "Two")
With Me.DataGridView1.Columns(columnindex)
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
.FillWeight = 20
End With
Me.DataGridView1.Rows.Add({"sample text", "1"})
Me.DataGridView1.Rows.Add({"another sample text", "2"})

Listview AutoReziseColumns not working

ListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
Listview1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent)
I'm having an issue since both of these lines separately produce the same result, which is resizing both the ColumnContent and the HeaderSize simultaneously.
I've searched and come up with no answer for this, i only need to resize by the HeaderSize but with the above example it seems not to be working correctly... or am i missing something?
And i've tested with more than one listview control...
Edit: I'm using it like this:
Private Sub UserListResize()
If Me.UserList.InvokeRequired Then
Me.UserList.Invoke(Sub() UserListResize())
Else
UserList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
End If
End Sub
I'm calling this when i'm finished with adding items on the listview.
They dont do the exactly the same thing, but it is sometimes hard to tell them apart.
HeaderSize resizes each column to the greater of HeaderText.Length or longest cell content, thereby never clipping the header text.
ColumnContent resizes to longest cell content which will clip header text if the HeaderText is longer then the content. Test this with a column containing 1 or 2 digits/characters, but a long header like "FooBar Counter of Foo".
Neither mode will clip column text though, which means when you are economic with header text, it can look like they do the same thing. Other things to consider:
The LV must have items in it for ColumnContent to be meaningful
Inspite of Auto in the name, it is not a persistent setting - as soon as you add something else the layout may be incorrect, so you may have to reset it periodically.
You can always lay them out how you want and set AllowColumnResize to False
You set AutoResizeColumn on a per column basis (note it is singular)
Individual column widths can be "auto sized" using the Width Property and the Magic Numbers of -1 (set to content) or -2 (size to Header). This allows you to only apply the AutoResize logic to only some columns or use a different setting depending on the column:
For n As Integer = 0 To myLV.Columns.Count -1 Step 2 ' just do every other
myLV.Columns.Width = -2 ' -2 = size to column header text
' -1 = size to longest content
Next n
One place this is very handy is when adding columns dynamically. Rather than guessing at the TextExtent, you can set the new column's width to something at least somewhat applicable to start with, then change it the first time content is added. Reference: MSDN ColumnHeader Width Property.

ZedGraph Axis labels

I have two questions about axis labels:
How do I make a label at the Y2-axis, that shows a highlighted label following the dynamic price (y2-value) of the last bar/candlestick? As the red label in this example:
And possibly also the same on the XAxis, showing the time of the last bar.
Also I wonder how to make the time axis plot only every 30 min, and also that it should be full half hours, not arbitrary 30 min spots.. As also shown in the above image.
ZedGraph is awesome. But takes some time to figure out the tricks and tweaks.. :)
Ad. 1.
You probably need to create a custom text object. If I remember correctly:
TextObj label = new TextObj("some text", 1, y2coordinate);
label.Location.CoordinateFrame = CoordType.XChartFractionY2Scale;
label.Location.AlignH = AlignH.Left;
myPane.GraphObjList.Add(label);
to change the color and background, just edit properties of label.FontSpec
Ad. 2.
You need to set manualy the Min, Max and MajorStep of the Scale object of your axis.