Jahreskalender erstellen - wer kann helfen?

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Kasi.

    Jahreskalender erstellen - wer kann helfen?

    Hallo!

    Ich versuche nun schon seit einiger Zeit einen Jahreskalender zu erstellen.
    Sei es mit vb.net, WPF, UserControls oder DataGridViews..
    ..alles klappt nicht so wirklich!

    Ich hatte angefangen mir ein UserControl für die Darstellung eines Tages im Jahreskalender zu basteln. Als ich dieses dann aber 372 auf der Form platziert hatte lies die Performance in Bezug auf Neuzeichnen des Forms sehr zu wünschen übrig.
    Danach hatte ich dann versucht mir eine

    VB.NET-Quellcode

    1. ​Public Class CustomDataGridViewCell
    mit

    VB.NET-Quellcode

    1. ​Inherits DataGridViewCell
    zu erstellen. Das klappte noch am besten, obwohl auch dort das erstellen und Größenänderungen an der Form
    sehr "Rechenintensiv" sind!

    Kennt von Euch vllt. jemand eine Möglichkeit einen Jahreskalender zu erstellen der nicht so auf die Leistung geht? Oder vllt. ein Control zum download was das kann?

    Der Jahreskalender soll, außer die Daten des Tages anzeigen, auch die Möglichkeit bieten Text einzufügen und etwaige Ferien oder Feiertage anzuzeigen (die Berechnungen dafür sind vorhanden)
    Er soll auch Vermerke darstellen können ob an diesem Tag ein Termin geplant ist.

    Also mit dem "CustomDataGridViewCell" klappte das noch am besten!

    CustomDataGridViewCell:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class CustomDataGridViewCell
    2. Inherits DataGridViewCell
    3. Private ReadOnly textBox As TextBox
    4. Private ReadOnly button1 As Button
    5. Private ReadOnly button2 As Button
    6. Private ReadOnly button3 As Button
    7. Private ReadOnly button4 As Button
    8. Public Sub New()
    9. textBox = New TextBox With {
    10. .Visible = False,
    11. .TextAlign = HorizontalAlignment.Left,
    12. .Multiline = True,
    13. .WordWrap = True
    14. }
    15. button1 = New Button With {
    16. .Text = "Button 1",
    17. .Visible = False
    18. }
    19. button2 = New Button With {
    20. .Text = "Button 2",
    21. .Visible = False
    22. }
    23. button3 = New Button With {
    24. .Text = "Button 3",
    25. .Visible = False
    26. }
    27. button4 = New Button With {
    28. .Text = "Button 4",
    29. .Visible = False
    30. }
    31. ' Weise den Buttons die korrekte Größe zu
    32. button1.Size = New Size(15, 15)
    33. button2.Size = New Size(15, 15)
    34. button3.Size = New Size(15, 15)
    35. button4.Size = New Size(15, 15)
    36. SetDoubleBuffered(button1, True)
    37. SetDoubleBuffered(button2, True)
    38. SetDoubleBuffered(button3, True)
    39. SetDoubleBuffered(button4, True)
    40. SetDoubleBuffered(textBox, True)
    41. 'SetDoubleBuffered(CType(Me, Control), True)
    42. End Sub
    43. 'Public Shared Narrowing Operator CType(v As CustomDataGridViewCell) As Control
    44. ' Throw New NotImplementedException()
    45. 'End Operator
    46. Public Shared Sub SetDoubleBuffered(c As Control, b As Boolean)
    47. If SystemInformation.TerminalServerSession Then Return
    48. Dim aProp As Reflection.PropertyInfo =
    49. GetType(Control).GetProperty("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
    50. aProp.SetValue(c, b, Nothing)
    51. End Sub
    52. Protected Overrides Sub Paint(graphics As Graphics,
    53. clipBounds As Rectangle,
    54. cellBounds As Rectangle,
    55. rowIndex As Integer,
    56. cellState As DataGridViewElementStates,
    57. value As Object,
    58. formattedValue As Object,
    59. errorText As String,
    60. cellStyle As DataGridViewCellStyle,
    61. advancedBorderStyle As DataGridViewAdvancedBorderStyle,
    62. paintParts As DataGridViewPaintParts)
    63. MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
    64. If cellState = DataGridViewElementStates.Selected Then
    65. graphics.FillRectangle(New SolidBrush(cellStyle.SelectionBackColor), cellBounds)
    66. Else
    67. graphics.FillRectangle(New SolidBrush(cellStyle.BackColor), cellBounds)
    68. End If
    69. Dim textBoxBounds As Rectangle = cellBounds
    70. textBoxBounds.X += 2
    71. textBoxBounds.Width -= button1.Width * 2 ' Platz für zwei Buttons nebeneinander
    72. textBoxBounds.Inflate(-1, -2)
    73. textBox.Bounds = textBoxBounds
    74. textBox.Text = If(formattedValue IsNot Nothing, formattedValue.ToString(), "")
    75. Dim buttonGroupBounds As New Rectangle(textBoxBounds.Right - 2, textBoxBounds.Top - 2, button1.Width * 2, textBoxBounds.Height - 4)
    76. button1.Bounds = New Rectangle(buttonGroupBounds.Left + 2, buttonGroupBounds.Top + 1, button1.Width, button1.Height)
    77. button2.Bounds = New Rectangle(buttonGroupBounds.Left + 2, buttonGroupBounds.Top + button1.Height, button2.Width, button2.Height)
    78. button3.Bounds = New Rectangle(buttonGroupBounds.Right - button3.Width, buttonGroupBounds.Top + 1, button3.Width, button3.Height)
    79. button4.Bounds = New Rectangle(buttonGroupBounds.Right - button4.Width, buttonGroupBounds.Top + button3.Height, button4.Width, button4.Height)
    80. textBox.Visible = True
    81. button1.Visible = True
    82. button2.Visible = True
    83. button3.Visible = True
    84. button4.Visible = True
    85. textBox.Focus()
    86. textBox.BorderStyle = BorderStyle.None
    87. button1.FlatStyle = FlatStyle.Flat
    88. button2.FlatStyle = FlatStyle.Flat
    89. button3.FlatStyle = FlatStyle.Flat
    90. button4.FlatStyle = FlatStyle.Flat
    91. textBox.Parent = DataGridView
    92. button1.Parent = DataGridView
    93. button2.Parent = DataGridView
    94. button3.Parent = DataGridView
    95. button4.Parent = DataGridView
    96. ' Berechne die erforderliche Höhe der Zelle und setze die Zellenhöhe
    97. Dim requiredHeight As Integer = CalculateCellHeight(rowIndex)
    98. Me.DataGridView.Rows(rowIndex).Height = requiredHeight + 1
    99. ' Berechne die erforderliche Breite der Zelle und setze die Zellenbreite
    100. Dim requiredWidth As Integer = CalculateCellWidth(rowIndex)
    101. 'Me.DataGridView.Columns(ColumnIndex).Width = requiredWidth
    102. End Sub
    103. Private Function CalculateCellHeight(rowIndex As Integer) As Integer
    104. ' Führe hier die Berechnung der erforderlichen Höhe basierend auf den Controls durch
    105. Dim textBoxHeight As Integer = textBox.Height
    106. Dim buttonGroupHeight As Integer = Math.Max(button1.Height + button2.Height, button3.Height + button4.Height)
    107. Dim requiredHeight As Integer = Math.Max(textBoxHeight, buttonGroupHeight)
    108. Return requiredHeight
    109. End Function
    110. Private Function CalculateCellWidth(rowIndex As Integer) As Integer
    111. ' Führe hier die Berechnung der erforderlichen Breite basierend auf den Controls durch
    112. Dim textBoxWidth As Integer = textBox.Width
    113. Dim buttonGroupWidth As Integer = button1.Width + button2.Width + button3.Width + button4.Width
    114. Dim requiredWidth As Integer = Math.Max(textBoxWidth, buttonGroupWidth)
    115. Return requiredWidth
    116. End Function
    117. Protected Overrides Sub OnEnter(rowIndex As Integer, throughMouseClick As Boolean)
    118. MyBase.OnEnter(rowIndex, throughMouseClick)
    119. textBox.Visible = True
    120. button1.Visible = True
    121. button2.Visible = True
    122. button3.Visible = True
    123. End Sub
    124. Protected Overrides Sub OnLeave(rowIndex As Integer, throughMouseClick As Boolean)
    125. MyBase.OnLeave(rowIndex, throughMouseClick)
    126. textBox.Visible = False
    127. button1.Visible = False
    128. button2.Visible = False
    129. button3.Visible = False
    130. End Sub
    131. Public Overrides ReadOnly Property EditType As Type
    132. Get
    133. Return GetType(CustomCellEditingControl)
    134. End Get
    135. End Property
    136. Public Overrides Property ValueType As Type
    137. Public Overrides ReadOnly Property DefaultNewRowValue As Object
    138. Get
    139. Return ""
    140. End Get
    141. End Property
    142. Public Overrides ReadOnly Property FormattedValueType As Type
    143. Get
    144. Return GetType(String)
    145. End Get
    146. End Property
    147. Public Overrides Property [ReadOnly] As Boolean
    148. Public Class CustomCellEditingControl
    149. Inherits TextBox
    150. Implements IDataGridViewEditingControl
    151. Private dataGridView As DataGridView
    152. Private rowIndex As Integer
    153. Private valueChanged As Boolean = False
    154. Public Sub ApplyCellStyleToEditingControl(dataGridViewCellStyle As DataGridViewCellStyle) Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
    155. Font = dataGridViewCellStyle.Font
    156. ForeColor = dataGridViewCellStyle.ForeColor
    157. BackColor = dataGridViewCellStyle.BackColor
    158. End Sub
    159. Public Property EditingControlDataGridView As DataGridView Implements IDataGridViewEditingControl.EditingControlDataGridView
    160. Get
    161. Return dataGridView
    162. End Get
    163. Set(value As DataGridView)
    164. dataGridView = value
    165. End Set
    166. End Property
    167. Public Property EditingControlFormattedValue As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
    168. Get
    169. Return Text
    170. End Get
    171. Set(value As Object)
    172. Text = value.ToString()
    173. End Set
    174. End Property
    175. Public Property EditingControlRowIndex As Integer Implements IDataGridViewEditingControl.EditingControlRowIndex
    176. Get
    177. Return rowIndex
    178. End Get
    179. Set(value As Integer)
    180. rowIndex = value
    181. End Set
    182. End Property
    183. Public Property EditingControlValueChanged As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged
    184. Get
    185. Return valueChanged
    186. End Get
    187. Set(value As Boolean)
    188. valueChanged = value
    189. End Set
    190. End Property
    191. Public ReadOnly Property EditingPanelCursor As Cursor Implements IDataGridViewEditingControl.EditingPanelCursor
    192. Get
    193. Return MyBase.Cursor
    194. End Get
    195. End Property
    196. Public Function GetEditingControlFormattedValue(context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
    197. Return Me.Text
    198. End Function
    199. Public Sub PrepareEditingControlForEdit(selectAll As Boolean) Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
    200. ' Nothing to do here
    201. End Sub
    202. Public Function EditingControlWantsInputKey(keyData As Keys, dataGridViewWantsInputKey As Boolean) As Boolean Implements IDataGridViewEditingControl.EditingControlWantsInputKey
    203. Return True
    204. End Function
    205. Public ReadOnly Property RepositionEditingControlOnValueChange As Boolean Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
    206. Get
    207. Return False
    208. End Get
    209. End Property
    210. Protected Overrides Sub OnTextChanged(e As EventArgs)
    211. valueChanged = True
    212. EditingControlDataGridView.NotifyCurrentCellDirty(True)
    213. MyBase.OnTextChanged(e)
    214. End Sub
    215. End Class
    216. End Class


    Form.Load:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. CustomDataGridViewCell.SetDoubleBuffered(DataGridView1, True)
    3. Dim customColumn As DataGridViewColumn
    4. For i = 1 To 12
    5. customColumn = New DataGridViewColumn(New CustomDataGridViewCell()) With {
    6. .HeaderText = "NewColumn" & i,
    7. .Name = "newColumn" & i,
    8. .Width = 200,
    9. .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
    10. }
    11. DataGridView1.Columns.Add(customColumn)
    12. Next
    13. DataGridView1.Rows.Clear()
    14. DataGridView1.Rows.Add(31)
    15. For Each row As DataGridViewRow In DataGridView1.Rows
    16. For Each cell As DataGridViewCell In row.Cells
    17. cell.Style = New DataGridViewCellStyle With {
    18. .Format = "CustomDataGridViewCell"
    19. }
    20. Next
    21. Next
    22. 'Me.Update()
    23. End Sub
    Ich denke, wenn du eine Jahresübersicht erstellst, die über 364 Steuerelemente umfasst, ist das ein Fehldesign. Gehe bei so einer Übersicht nicht gleich in die Tiefe der Tage, sondern Monate oder ev. noch Wochen...
    Es gibt da fertige Anwendungen, wie z.B. von @dive26 auf seiner Website zum Download.
    Da kannst du sehen, wie er so einen Kalender aufbaut... Vlt. hilft dir das weiter...
    @Morrison Kannst Du mal Deine grafischen Vorstellungen der GUI als Skizze posten?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Morrison
    Wie @VB1963 richtig geschrieben hat, habe ich mir so einen Kalender (netzwerkfähig für mein Team) selbst erstellt.
    Dabei habe ich aber lediglich Monatsansichten - also maximal 31 Tage angezeigt.

    Generell ist alles was über 256 Controls hinausgeht sehr performancehungrig (in VB6 durften es damals sogar nicht mehr als 256 Controls sein).

    Jeder Tag befindet sich in einem Panel mit einem Listview und ein paar Labels. Geht sehr zügig im Aufbau und reicht exakt für unseren Eigenbedarf im Büro.
    Im Hintergrund werkelt eine Access Datenbank (.mdb).

    In der Free-Version kostenfrei auf einem Rechner nutzbar.
    In der PRO-Version (Einmalzahlung, keine laufenden Kosten) auch von mehreren Rechnern im Netzwerk nutzbar.

    Infos und Download: bonit.at/simplecalendar.asp
    Bilder
    • 28052023104754.jpg

      354,42 kB, 1.489×1.082, 63 mal angesehen
    • 28052023104810.jpg

      127,26 kB, 726×423, 51 mal angesehen
    • 28052023104955.jpg

      136,28 kB, 955×597, 56 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Hi!

    Also es sollte schon eine Übersicht sämtlicher Tage im Jahr darstellen, zumal ich noch Monatsansichten und Tagesansichten umgesetzt habe!
    Das ganze soll ein kleines Unternehmensprojekt werden mit dem man hauptsächlich die Stundenarbeitszeit der Mitarbeiter planen kann(neben noch einiger anderer Funktionen).
    Für uns privat halt.


    Die Punkte stellen Termine dar, die man sicherlich zu einem Terminfeld zusammenfassen kann!
    Wichtig wäre jedoch das Ferien und Feiertage ersichtlich sind!
    Skizze:
    Bilder
    • Skizze.jpg

      66,82 kB, 494×396, 51 mal angesehen
    Wie sind folgende Punkte zueinander gewichtet, sofern sie vorgesehen sind:
    - Updategeschwindigkeit der GUI
    - Anzahl der dargestellten Daten-Einzelheiten (aktiv, inaktiv ~ Fokuszeile, Fokusspalte)
    - Anzahl der dargestellten Controls zur Bearbeitung der Termine
    - Zugriff auf hidden Funktionalität
    ...
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also am wichtigsten ist es das alle Datumsangaben angezeigt werden, also eine Komplettübersicht der Jahres-Daten.
    Dann wäre die Reaktionsfreudigkeit der GUI sehr wichtig.
    Des weiteren soll auch sofort ersichtlich sein ob das Datum ein Feier- bzw. Ferientag ist und ob an diesem Tag ein Termin vermerkt ist!
    Also es würde reichen wenn anstatt der vier Punkte nur einer vorgesehen ist, der, wenn Termin vorhanden oder nicht, halt dargestellt wird oder eben nicht.

    Also man könnte das "Layout" ja als Bitmap-Grafik darstellen, mit Koordinaten für die jeweiligen Tage.
    Das wäre wohl am performantesten!
    Muss es ein DGV sein oder ginge auch ein TablelLayoutPanel mit UserControls?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mit solchen Design-Fragen solltest Du Dich auseinandersetzen, bevor Du mit der Implementierung beginnst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!