VB.NET Multiple titles at same height in a windows forms chart - vb.net

How do I put multiple titles into a chart at the same height?
No matter what parameters I choose I get results similar to this. My last try before asking here.
The screen shot shows the titles with a backcolor to prove what I expected.
Whenever I add 2 titles WinForms automatically puts them in different heights.
The 3. line is custom added to show you what I want to have as a result.
I could write a method but it should react to resize events and solving this with docking or alignments is preferred.
So right now the titles are inside the chartarea because I was fiddling around with DockingOffsets etc. I want them to be on top of the chartarea.
Here is my code:
Friend Function CreateTitle(ByVal titleName As TitleName, ByVal chart As Chart) As Title
Dim font As Font = Nothing
Dim foreColor As Color = Nothing
Dim backColor As Color = Nothing
Dim alignment As ContentAlignment = Nothing
Dim dockingOffset As Integer
Dim name As String = String.Empty
Dim titleText As String = String.Empty
Dim dockedToChartArea As String = String.Empty
Dim docking As Docking = Nothing
' Default settings
font = New Font("Arial", 12)
foreColor = color.blue
dockingOffset = 0
dockedToChartArea = chart.ChartAreas(0).Name
' Custom settings
Select Case titleName
Case ChartControls.TitleName.ComponentName
name = TITLENAME_COMP
titleText = chart.Name
alignment = ContentAlignment.BottomLeft
dockingOffset = 0
docking = DataVisualization.Charting.Docking.Top
backColor = Color.Coral
Case ChartControls.TitleName.TrafficLight
name = TITLENAME_TRAFFICLIGHT
titleText = "+34.6% / 1800 €"
alignment = ContentAlignment.TopRight
dockingOffset = 0
docking = DataVisualization.Charting.Docking.Top
backColor = Color.Beige
End Select
Dim title As New Title(titleText)
title.Name = name
title.Font = font
title.ForeColor = foreColor
title.BackColor = backColor
title.Alignment = alignment
title.Position = New ElementPosition()
title.Docking = docking
title.DockingOffset = dockingOffset
title.DockedToChartArea = dockedToChartArea
Return title
End Function
I call this method twice with different parameters and add them to my Titles collection.

I had to change my workaround because of requirements. It would have been very time consuming to make my workaround work for 1 .. n charts that differ in size depending on the amount of charts because then the labels would need a different size and position. So I had to find a better solution.
I have a Enum with 2 different title. The following properties are important.
Backcolor = Transparent
Only for one title choose a custom position. This turns the property "Position.Auto" to false. Take a look at my if clause at the end. So because the other property "Position.Auto" stays true because you don't manually change it you can simply assign a offset while bringing the other title manually to the same height.
.
`Friend Function CreateTitle(ByVal titleName As TitleName) As Title
Dim titleText As String = String.Empty
Dim alignment As ContentAlignment
' Custom settings
Select Case titleName
Case ChartControls.TitleName.Title1
titleText = "Title1"
alignment = ContentAlignment.MiddleLeft
Case ChartControls.TitleName.Title2
titleText = "Title2"
alignment = ContentAlignment.TopRight
End Select
Dim title As New Title()
title.Text = titleText
title.Font = New Font("Arial", 12)
title.BackColor = Color.Transparent
If titleName.Equals(CCT.ChartControls.TitleName.Title2) Then
title.Position = New ElementPosition(0, 3, 94, 5)
Else
title.DockingOffset = 0
End If
title.Alignment = alignment
Return title
End Function`
Looks like this: 2 titles on same height.

Related

Unexpected TableLayoutPanel Behavour

Hi having some issues with some nested tablelayoutpanels in a custom control
I have a tablelayoutpanel in a tablelayoutpanel in a tablelayoutpanel Crazy i know but it keeps it uniform and ordered
The custom control consists of 2 tablelayoutpanels that is placed in a table layout panel on a form and in a preview area of my main form.
Having them set at design time works fine but dynamically adding / removing the topmost ones with 1 row 2 columns into the one below it that has 1 column and x rows only Seems to break the autosizing behavior I'm chasing.
So I want the cells & rows to resize automatically based on the contents in this case labels but still remain in a neat ordered layout
There's no docking anywhere in the hierarchy of controls just anchors here and there
Here's my code to add the tablelayoutpanels below
"https://i.stack.imgur.com/vRfhE.png"
Private Sub AddControl(ByRef Counter As Counter)
Dim Gpanel As New TableLayoutPanel
Dim tlabel As New Label
Dim clabel As New Label
Dim pad As Integer = Counter.Cpad
TLPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink
Gpanel.AutoSizeMode = AutoSizeMode.GrowAndShrink
Gpanel.AutoSize = True
Gpanel.GrowStyle = TableLayoutPanelGrowStyle.AddRows
Gpanel.BorderStyle = BorderStyle.FixedSingle
Gpanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Inset
TLPanel.BorderStyle = BorderStyle.FixedSingle
Gpanel.Dock = DockStyle.None
Gpanel.Padding = New Padding(0)
Gpanel.Anchor = AnchorStyles.Top Or AnchorStyles.Left
Gpanel.BackColor = Color.Transparent
Gpanel.RowCount = 1
Gpanel.ColumnCount = 2
Gpanel.RowStyles.Add(New RowStyle(SizeType.AutoSize))
Gpanel.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
Gpanel.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
tlabel.Dock = DockStyle.None
clabel.Dock = DockStyle.None
tlabel.GetPreferredSize(Size.Empty)
clabel.GetPreferredSize(Size.Empty)
tlabel.Text = Counter.Clabel
clabel.Text = Counter.Ccount.ToString
tlabel.Padding = New Padding(pad)
clabel.Padding = New Padding(pad)
tlabel.Anchor = AnchorStyles.None
clabel.Anchor = AnchorStyles.None
tlabel.ForeColor = Color.FromName(Counter.Clcolor)
clabel.ForeColor = Color.FromName(Counter.Ccolor)
Dim fontstyle As New FontStyle
fontstyle = Counter.ClfontStyle
tlabel.Font = New Font(Counter.Clfont, Counter.Clfontsize, fontstyle)
fontstyle = Counter.CcfontStyle
clabel.Font = New Font(Counter.Ccfont, Counter.Ccfontsize, fontstyle)
Gpanel.Controls.Add(tlabel, 0, 0)
Gpanel.Controls.Add(clabel, 1, 0)
TLPanel.Controls.Add(Gpanel, 0, Counter.ID)
TLPanel.RowCount += 1
TLPanel.RowStyles.Add(New RowStyle(SizeType.AutoSize))
Dim Styles As TableLayoutRowStyleCollection = TLPanel.RowStyles
Dim Cstyles As TableLayoutColumnStyleCollection = Gpanel.ColumnStyles
Gpanel.RowStyles.Item(0) = New RowStyle(SizeType.AutoSize)
TLPanel.ColumnStyles.Item(0) = New ColumnStyle(SizeType.AutoSize)
For i = 0 To Cstyles.Count - 1
Cstyles.Item(i) = New ColumnStyle(SizeType.AutoSize)
Next
For i = 0 To Styles.Count - 1
Styles.Item(i) = New RowStyle(SizeType.AutoSize)
Next
TLPanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Inset
AutoSize = True
AutoSizeMode = AutoSizeMode.GrowAndShrink
End Sub
'

Dynamic entries from textfiles into FlowLayoutPanel

I'm currently working on a ToDo program, where you can simply add notes. (With the option to set priority and attachment) The Note will be saved as a textfile. Now I want to make an over view of the ToDo's which have to be done. In the end it's supposed to look like a list, one row for each Note, built like this:
TITLE.............................[Attachment Icon]..[Priority Icon]..[CheckBox]
The checkbox should always be on the very right side of the row.
My idea is to add a FlowLayoutPanel to a FlowLayoutPanel for every Note. In the child-FlowLayoutPanel I'll add the controls. My problem is that I have no Idea how to set the positions of the controls. I tried to add a label and use it as a space between the title and the other controls, but it doesn't really work.
Here's the code I currently have:
For Each File In Directory.GetFiles(myPath)
Dim tlp As New FlowLayoutPanel
tlp.BackColor = Color.Gray
tlp.Width = 260
tlp.FlowDirection = FlowDirection.TopDown
Dim lbl As New Label
lbl.AutoSize = True
lbl.Text = getInsert(File, 0)
lbl.Anchor = AnchorStyles.Right
lbl.ForeColor = Color.White
AddHandler lbl.Click, Sub() Me.getInsert(File, 0)
tlp.Height = 40
Dim cbx As New CheckBox
cbx.FlatStyle = FlatStyle.Flat
cbx.Text = ""
cbx.Width = 15
cbx.Height = 30
AddHandler cbx.CheckStateChanged, Sub() Me.deleteEntry(tlp)
Dim space As New Label
space.AutoSize = False
space.Text = ""
space.Height = 30
space.Anchor = AnchorStyles.Right
tlp.Controls.Add(lbl)
tlp.Controls.Add(Space)
tlp.Controls.Add(cbx)
Space.Width = tlp.Width - lbl.Width - cbx.Width - 15
mfp.Controls.Add(tlp)
Next
Here's an example:
todo_example
I hope anyone has a good idea how to solve this problem.
Thanks in advance :)

ComboBox DrawItem event handling for Font Combo Box - WinForms, VB.NET

I am creating a combobox which shows fonts in the list, with every font item displayed in its own font style. The combobox loads without errors but the list that shows is all in just one font. I have set DrawMode = OwnerDrawVariable and IntegralHeight = false, but still no result. The DrawItem code that you can see here is from the MSDN website, with a few changes as per my requirement. Here is my code:
BindCOmboboxes() is called when the form loads.
Private Sub w_BindComboBoxes() (StyleControl is a User Control containing the combobox)
'Set Properties
Dim tFont As Font = Nothing
StyleControl.TS1Font.DrawMode = DrawMode.OwnerDrawVariable
For Each fntfam As FontFamily In FontFamily.Families
If fntfam.IsStyleAvailable(FontStyle.Regular) Then
tFont = New Font(fntfam, 12, FontStyle.Regular)
StyleControl.TS1Font.Items.Add(tFont.Name & ",Regular")
End If
If fntfam.IsStyleAvailable(FontStyle.Italic) Then
tFont = New Font(fntfam, 12, FontStyle.Italic)
StyleControl.TS1Font.Items.Add(tFont.Name & ",Italic")
End If
If fntfam.IsStyleAvailable(FontStyle.Bold) Then
tFont = New Font(fntfam, 12, FontStyle.Bold)
StyleControl.TS1Font.Items.Add(tFont.Name & ",Bold")
End If
Next
End Sub
DrawItem function for TS1Font combobox
Private Sub FontComboBoxDrawItems(sender As Object, e As DrawItemEventArgs)
Dim size As Integer = 12
Dim myFont As System.Drawing.Font
Dim family As FontFamily = new FontFamily("Arial", 12) <-- to avoid crash
Dim fntStyle As FontStyle = FontStyle.Regular <-- To avoid crash
Dim animalColor As System.Drawing.Color = Color.Black
Dim str As String = DirectCast(sender, ComboBox).Items(e.Index).ToString.Trim
Dim brk() As String = str.Split(",")
For Each fam As FontFamily In FontFamily.Families
If fam.Name = brk(0) Then family = fam
Next
Select Case brk(1)
Case "Regular"
fntStyle = FontStyle.Regular
Case "Bold"
fntStyle = FontStyle.Bold
Case "Italic"
fntStyle = FontStyle.Italic
End Select
' Draw the background of the item.
e.DrawBackground()
' Draw each string in the array, using a different size, color,
' and font for each item.
myFont = New Font(family, size, fntStyle)
e.Graphics.DrawString(DirectCast(sender, ComboBox).Items(e.Index).ToString, myFont, System.Drawing.Brushes.Black,
New PointF(e.Bounds.X, e.Bounds.Y))
' Draw the focus rectangle if the mouse hovers over an item.
e.DrawFocusRectangle()
End Sub
On debugging in the DrawItem function, the values in the statement e.Graphics.DrawString = shows proper font family, style and size values. So why doesn't it draw the items that way?
Result:

Custom colors on bar chart using Zedgraph library

Am using Zedgraph chart library but I can't seem to be able to color a bar graph depending on a specific condition. Am following along with the example found on this tutorial.
In my case, if the value isn't above 50 -which is the student.pass_mark variable-, I want to color the bar red and if its above 50 I want to color it green. Below is my code. Which so far only gives me red even though I have values of 100, 80, 110 etc.
Dim subject As String
Dim grade As Decimal
Dim colors As Color() = {}
Dim subject_names As String() = {}
For i = 0 To student.no_of_subjects
ReDim Preserve colors(i)
ReDim Preserve subject_names(i)
subject = student.subject_name
grade = student.grade
Dim x As Double = CDbl(i) + 1
Dim y As Double = grade
Dim z As Double = 0
list.Add(x, y, z)
If grade < student.pass_mark Then
colors(i) = Color.Red
Else
colors(i) = Color.Green
End If
subject_names(i) = subject
Next
Dim myCurve As BarItem = myPane.AddBar("Student Subject", list, Color.Blue)
'Dim colors As Color() = {Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Purple}
myCurve.Bar.Fill = New Fill(colors)
myCurve.Bar.Fill.Type = FillType.Solid
myCurve.Bar.Fill.RangeMin = 0
myCurve.Bar.Fill.RangeMax = 4
myPane.Chart.Fill = New Fill(Color.White, Color.FromArgb(220, 220, 255), 45)
myPane.Fill = New Fill(Color.White, Color.FromArgb(255, 255, 225), 45)
' Tell ZedGraph to calculate the axis ranges
' Set the XAxis labels
myPane.XAxis.Scale.TextLabels = subject_names
' Set the XAxis to Text type
myPane.XAxis.Type = ZedGraph.AxisType.Text
ZedChart.IsShowPointValues = True
ZedChart.AxisChange()
ZedChart.Refresh()
Also, I want to draw a line across the whole chart that shows the pass_mark so that it is quickly visible that a student' has or hasn't passed a certain subject in comparison to the passmark
I don't know whether it is still relative but you can do multi-colored bar plots in ZedGraph.
You can find the tutorial here:
http://zedgraph.dariowiz.com/indexb806.html?title=Multi-Colored_Bar_Demo
In your case you can use FillType.GradientByColorValue I assume.
For the line you can simply add a LineObj to the myPane.GraphObjList

Controls are not added to tabpage VB.NET

I run the following code in the constructor of a window. The "label" gets added but none of the other controls are shown on screen. If I debug the newTab.Controls there are several controls in it. Why don't they show up on the screen and I only see the "label" control.
Thanks
Dim graphlist As ArrayList = New ArrayList
For Each funct As TL_FUNCTION In functionlist
If (funct.functionname = functi) Then
If Not (graphlist.Contains(funct.picture)) Then
graphlist.Add(funct.picture)
End If
End If
Next
For Each picture In graphlist
Dim NewTab As New TabPage
NewTab.Name = picture
NewTab.Text = NewTab.Name
Me.TabControl1.Controls.Add(NewTab)
Me.TabControl1.SelectedIndex = Me.TabControl1.TabCount - 1
For Each func As TL_FUNCTION In functionlist
If (func.picture = picture) Then
Dim label As Label = New Label
label.Text = func.curve.ToString
NewTab.Controls.Add(label) 'This label shows up
Dim key As String
Dim values() As String
For Each key In func.values.Keys
values = func.values.GetValues(key)
For Each value As String In values
Dim label2 As New Label
label2.Text = key.ToString
Dim textb As TextBox = New TextBox
textb.Text = value
NewTab.Controls.Add(label2) 'this one is not shown on the tab
NewTab.Controls.Add(textb) 'this one is not shown on the tab
Next value
Next key
End If
Next
Next
You are placing the new labels and textboxes underneath the new label that you see in the TabPage because you never set their location, so it defaults to point (0, 0).
Try setting the location for the controls:
For Each value As String In values
Dim label2 As New Label
label2.Text = key.ToString
label2.Location = New Point(10, NewTab.Controls.Count * 24)
Dim textb As TextBox = New TextBox
textb.Text = value
textb.Location = New Point(label2.Right + 4, label2.Top)
NewTab.Controls.Add(label2)
NewTab.Controls.Add(textb)
Next value