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 mit 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
Form.Load:
Spoiler anzeigen
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 mit 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:
VB.NET-Quellcode
-
- Public Class CustomDataGridViewCell
- Inherits DataGridViewCell
- Private ReadOnly textBox As TextBox
- Private ReadOnly button1 As Button
- Private ReadOnly button2 As Button
- Private ReadOnly button3 As Button
- Private ReadOnly button4 As Button
- Public Sub New()
- textBox = New TextBox With {
- .Visible = False,
- .TextAlign = HorizontalAlignment.Left,
- .Multiline = True,
- .WordWrap = True
- }
- button1 = New Button With {
- .Text = "Button 1",
- .Visible = False
- }
- button2 = New Button With {
- .Text = "Button 2",
- .Visible = False
- }
- button3 = New Button With {
- .Text = "Button 3",
- .Visible = False
- }
- button4 = New Button With {
- .Text = "Button 4",
- .Visible = False
- }
- ' Weise den Buttons die korrekte Größe zu
- button1.Size = New Size(15, 15)
- button2.Size = New Size(15, 15)
- button3.Size = New Size(15, 15)
- button4.Size = New Size(15, 15)
- SetDoubleBuffered(button1, True)
- SetDoubleBuffered(button2, True)
- SetDoubleBuffered(button3, True)
- SetDoubleBuffered(button4, True)
- SetDoubleBuffered(textBox, True)
- 'SetDoubleBuffered(CType(Me, Control), True)
- End Sub
- 'Public Shared Narrowing Operator CType(v As CustomDataGridViewCell) As Control
- ' Throw New NotImplementedException()
- 'End Operator
- Public Shared Sub SetDoubleBuffered(c As Control, b As Boolean)
- If SystemInformation.TerminalServerSession Then Return
- Dim aProp As Reflection.PropertyInfo =
- GetType(Control).GetProperty("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
- aProp.SetValue(c, b, Nothing)
- End Sub
- Protected Overrides Sub Paint(graphics As Graphics,
- clipBounds As Rectangle,
- cellBounds As Rectangle,
- rowIndex As Integer,
- cellState As DataGridViewElementStates,
- value As Object,
- formattedValue As Object,
- errorText As String,
- cellStyle As DataGridViewCellStyle,
- advancedBorderStyle As DataGridViewAdvancedBorderStyle,
- paintParts As DataGridViewPaintParts)
- MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
- If cellState = DataGridViewElementStates.Selected Then
- graphics.FillRectangle(New SolidBrush(cellStyle.SelectionBackColor), cellBounds)
- Else
- graphics.FillRectangle(New SolidBrush(cellStyle.BackColor), cellBounds)
- End If
- Dim textBoxBounds As Rectangle = cellBounds
- textBoxBounds.X += 2
- textBoxBounds.Width -= button1.Width * 2 ' Platz für zwei Buttons nebeneinander
- textBoxBounds.Inflate(-1, -2)
- textBox.Bounds = textBoxBounds
- textBox.Text = If(formattedValue IsNot Nothing, formattedValue.ToString(), "")
- Dim buttonGroupBounds As New Rectangle(textBoxBounds.Right - 2, textBoxBounds.Top - 2, button1.Width * 2, textBoxBounds.Height - 4)
- button1.Bounds = New Rectangle(buttonGroupBounds.Left + 2, buttonGroupBounds.Top + 1, button1.Width, button1.Height)
- button2.Bounds = New Rectangle(buttonGroupBounds.Left + 2, buttonGroupBounds.Top + button1.Height, button2.Width, button2.Height)
- button3.Bounds = New Rectangle(buttonGroupBounds.Right - button3.Width, buttonGroupBounds.Top + 1, button3.Width, button3.Height)
- button4.Bounds = New Rectangle(buttonGroupBounds.Right - button4.Width, buttonGroupBounds.Top + button3.Height, button4.Width, button4.Height)
- textBox.Visible = True
- button1.Visible = True
- button2.Visible = True
- button3.Visible = True
- button4.Visible = True
- textBox.Focus()
- textBox.BorderStyle = BorderStyle.None
- button1.FlatStyle = FlatStyle.Flat
- button2.FlatStyle = FlatStyle.Flat
- button3.FlatStyle = FlatStyle.Flat
- button4.FlatStyle = FlatStyle.Flat
- textBox.Parent = DataGridView
- button1.Parent = DataGridView
- button2.Parent = DataGridView
- button3.Parent = DataGridView
- button4.Parent = DataGridView
- ' Berechne die erforderliche Höhe der Zelle und setze die Zellenhöhe
- Dim requiredHeight As Integer = CalculateCellHeight(rowIndex)
- Me.DataGridView.Rows(rowIndex).Height = requiredHeight + 1
- ' Berechne die erforderliche Breite der Zelle und setze die Zellenbreite
- Dim requiredWidth As Integer = CalculateCellWidth(rowIndex)
- 'Me.DataGridView.Columns(ColumnIndex).Width = requiredWidth
- End Sub
- Private Function CalculateCellHeight(rowIndex As Integer) As Integer
- ' Führe hier die Berechnung der erforderlichen Höhe basierend auf den Controls durch
- Dim textBoxHeight As Integer = textBox.Height
- Dim buttonGroupHeight As Integer = Math.Max(button1.Height + button2.Height, button3.Height + button4.Height)
- Dim requiredHeight As Integer = Math.Max(textBoxHeight, buttonGroupHeight)
- Return requiredHeight
- End Function
- Private Function CalculateCellWidth(rowIndex As Integer) As Integer
- ' Führe hier die Berechnung der erforderlichen Breite basierend auf den Controls durch
- Dim textBoxWidth As Integer = textBox.Width
- Dim buttonGroupWidth As Integer = button1.Width + button2.Width + button3.Width + button4.Width
- Dim requiredWidth As Integer = Math.Max(textBoxWidth, buttonGroupWidth)
- Return requiredWidth
- End Function
- Protected Overrides Sub OnEnter(rowIndex As Integer, throughMouseClick As Boolean)
- MyBase.OnEnter(rowIndex, throughMouseClick)
- textBox.Visible = True
- button1.Visible = True
- button2.Visible = True
- button3.Visible = True
- End Sub
- Protected Overrides Sub OnLeave(rowIndex As Integer, throughMouseClick As Boolean)
- MyBase.OnLeave(rowIndex, throughMouseClick)
- textBox.Visible = False
- button1.Visible = False
- button2.Visible = False
- button3.Visible = False
- End Sub
- Public Overrides ReadOnly Property EditType As Type
- Get
- Return GetType(CustomCellEditingControl)
- End Get
- End Property
- Public Overrides Property ValueType As Type
- Public Overrides ReadOnly Property DefaultNewRowValue As Object
- Get
- Return ""
- End Get
- End Property
- Public Overrides ReadOnly Property FormattedValueType As Type
- Get
- Return GetType(String)
- End Get
- End Property
- Public Overrides Property [ReadOnly] As Boolean
- Public Class CustomCellEditingControl
- Inherits TextBox
- Implements IDataGridViewEditingControl
- Private dataGridView As DataGridView
- Private rowIndex As Integer
- Private valueChanged As Boolean = False
- Public Sub ApplyCellStyleToEditingControl(dataGridViewCellStyle As DataGridViewCellStyle) Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
- Font = dataGridViewCellStyle.Font
- ForeColor = dataGridViewCellStyle.ForeColor
- BackColor = dataGridViewCellStyle.BackColor
- End Sub
- Public Property EditingControlDataGridView As DataGridView Implements IDataGridViewEditingControl.EditingControlDataGridView
- Get
- Return dataGridView
- End Get
- Set(value As DataGridView)
- dataGridView = value
- End Set
- End Property
- Public Property EditingControlFormattedValue As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
- Get
- Return Text
- End Get
- Set(value As Object)
- Text = value.ToString()
- End Set
- End Property
- Public Property EditingControlRowIndex As Integer Implements IDataGridViewEditingControl.EditingControlRowIndex
- Get
- Return rowIndex
- End Get
- Set(value As Integer)
- rowIndex = value
- End Set
- End Property
- Public Property EditingControlValueChanged As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged
- Get
- Return valueChanged
- End Get
- Set(value As Boolean)
- valueChanged = value
- End Set
- End Property
- Public ReadOnly Property EditingPanelCursor As Cursor Implements IDataGridViewEditingControl.EditingPanelCursor
- Get
- Return MyBase.Cursor
- End Get
- End Property
- Public Function GetEditingControlFormattedValue(context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
- Return Me.Text
- End Function
- Public Sub PrepareEditingControlForEdit(selectAll As Boolean) Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
- ' Nothing to do here
- End Sub
- Public Function EditingControlWantsInputKey(keyData As Keys, dataGridViewWantsInputKey As Boolean) As Boolean Implements IDataGridViewEditingControl.EditingControlWantsInputKey
- Return True
- End Function
- Public ReadOnly Property RepositionEditingControlOnValueChange As Boolean Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
- Get
- Return False
- End Get
- End Property
- Protected Overrides Sub OnTextChanged(e As EventArgs)
- valueChanged = True
- EditingControlDataGridView.NotifyCurrentCellDirty(True)
- MyBase.OnTextChanged(e)
- End Sub
- End Class
- End Class
Form.Load:
VB.NET-Quellcode
-
- Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- CustomDataGridViewCell.SetDoubleBuffered(DataGridView1, True)
- Dim customColumn As DataGridViewColumn
- For i = 1 To 12
- customColumn = New DataGridViewColumn(New CustomDataGridViewCell()) With {
- .HeaderText = "NewColumn" & i,
- .Name = "newColumn" & i,
- .Width = 200,
- .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
- }
- DataGridView1.Columns.Add(customColumn)
- Next
- DataGridView1.Rows.Clear()
- DataGridView1.Rows.Add(31)
- For Each row As DataGridViewRow In DataGridView1.Rows
- For Each cell As DataGridViewCell In row.Cells
- cell.Style = New DataGridViewCellStyle With {
- .Format = "CustomDataGridViewCell"
- }
- Next
- Next
- 'Me.Update()
- End Sub