I have a Winforms app with two ListViews in a SplitContainer.
When I drag the splitter to hide part of the Panel2 ListView items, it automatically adds a vertical scrollbar.
When I drag the splitter to hide part of the Panel1 ListView items, it does not add a vertical scrollbar.
Changing which ListView is in which Panel has the same behavior. It's as if something about the SplitContainer or its panels is controlling whether the vertical scrollbar is added to the ListView in Panel1 or not. How to make whichever ListView is in the top Panel1 also automatically add the vertical scrollbar?
To replicate, create a simple Winforms application with one form. Here is my form code followed by the designer form code.
Public Class Form1
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Try
Timer1.Enabled = False
TechDateList.BeginUpdate()
TechDateList.Items.Clear()
StopsList.BeginUpdate()
StopsList.Items.Clear()
For i As Integer = 1 To 5
Dim techItem = New ListViewItem
techItem.UseItemStyleForSubItems = False
techItem.SubItems(0).Text = Date.Now.ToString("MMM dd, yyyy")
techItem.SubItems.Add(String.Format("Tech {0}", i))
TechDateList.Items.Add(techItem)
Next
For i As Integer = 1 To 5
Dim stopItem = New ListViewItem
stopItem.UseItemStyleForSubItems = False
stopItem.SubItems(0).Text = Choose(i, "AAA", "BBB", "CCC", "DDD", "EEE")
stopItem.SubItems.Add(String.Format("Stop {0}", i))
StopsList.Items.Add(stopItem)
Next
Catch ex As Exception
MsgBox(ex.ToString(), MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "Timer1_Tick Error 1")
Finally
TechDateList.EndUpdate()
StopsList.EndUpdate()
End Try
Try
ListSplitter.Panel1Collapsed = False
ListSplitter.SplitterDistance = 125
ListSplitter.SplitterWidth = 6
TechDateList.Items.Item(0).Selected = True
Catch ex As Exception
MsgBox(ex.ToString(), MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "Timer1_Tick Error 2")
End Try
End Sub
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.ListSplitter = New System.Windows.Forms.SplitContainer()
Me.TechDateList = New System.Windows.Forms.ListView()
Me.UInitial = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.SchedDate = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.StopsList = New System.Windows.Forms.ListView()
Me.StopNum = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.StopName = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
CType(Me.ListSplitter, System.ComponentModel.ISupportInitialize).BeginInit()
Me.ListSplitter.Panel1.SuspendLayout()
Me.ListSplitter.Panel2.SuspendLayout()
Me.ListSplitter.SuspendLayout()
Me.SuspendLayout()
'
'ListSplitter
'
Me.ListSplitter.Dock = System.Windows.Forms.DockStyle.Fill
Me.ListSplitter.FixedPanel = System.Windows.Forms.FixedPanel.Panel1
Me.ListSplitter.Location = New System.Drawing.Point(0, 0)
Me.ListSplitter.Name = "ListSplitter"
Me.ListSplitter.Orientation = System.Windows.Forms.Orientation.Horizontal
'
'ListSplitter.Panel1
'
Me.ListSplitter.Panel1.Controls.Add(Me.TechDateList)
Me.ListSplitter.Panel1Collapsed = True
Me.ListSplitter.Panel1MinSize = 0
'
'ListSplitter.Panel2
'
Me.ListSplitter.Panel2.Controls.Add(Me.StopsList)
Me.ListSplitter.Size = New System.Drawing.Size(384, 261)
Me.ListSplitter.SplitterDistance = 25
Me.ListSplitter.SplitterWidth = 1
Me.ListSplitter.TabIndex = 1
'
'TechDateList
'
Me.TechDateList.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
Me.TechDateList.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.UInitial, Me.SchedDate})
Me.TechDateList.FullRowSelect = True
Me.TechDateList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.TechDateList.HideSelection = False
Me.TechDateList.LabelWrap = False
Me.TechDateList.Location = New System.Drawing.Point(4, 0)
Me.TechDateList.Margin = New System.Windows.Forms.Padding(0)
Me.TechDateList.MultiSelect = False
Me.TechDateList.Name = "TechDateList"
Me.TechDateList.ShowGroups = False
Me.TechDateList.Size = New System.Drawing.Size(258, 166)
Me.TechDateList.TabIndex = 0
Me.TechDateList.UseCompatibleStateImageBehavior = False
Me.TechDateList.View = System.Windows.Forms.View.Details
'
'UInitial
'
Me.UInitial.Text = "Route"
Me.UInitial.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.UInitial.Width = 100
'
'SchedDate
'
Me.SchedDate.Text = "Job Date"
Me.SchedDate.Width = 133
'
'StopsList
'
Me.StopsList.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
Me.StopsList.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.StopNum, Me.StopName})
Me.StopsList.FullRowSelect = True
Me.StopsList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.StopsList.HideSelection = False
Me.StopsList.LabelWrap = False
Me.StopsList.Location = New System.Drawing.Point(4, 0)
Me.StopsList.Margin = New System.Windows.Forms.Padding(0)
Me.StopsList.MultiSelect = False
Me.StopsList.Name = "StopsList"
Me.StopsList.ShowGroups = False
Me.StopsList.Size = New System.Drawing.Size(258, 252)
Me.StopsList.TabIndex = 0
Me.StopsList.UseCompatibleStateImageBehavior = False
Me.StopsList.View = System.Windows.Forms.View.Details
'
'StopNum
'
Me.StopNum.Text = "000"
Me.StopNum.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.StopNum.Width = 34
'
'StopName
'
Me.StopName.Text = "Stop Name"
Me.StopName.Width = 199
'
'Timer1
'
Me.Timer1.Interval = 250
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(384, 261)
Me.Controls.Add(Me.ListSplitter)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ListSplitter.Panel1.ResumeLayout(False)
Me.ListSplitter.Panel2.ResumeLayout(False)
CType(Me.ListSplitter, System.ComponentModel.ISupportInitialize).EndInit()
Me.ListSplitter.ResumeLayout(False)
Me.ResumeLayout(False)
End Sub
Friend WithEvents ListSplitter As SplitContainer
Friend WithEvents TechDateList As ListView
Friend WithEvents UInitial As ColumnHeader
Friend WithEvents SchedDate As ColumnHeader
Friend WithEvents StopsList As ListView
Friend WithEvents StopNum As ColumnHeader
Friend WithEvents StopName As ColumnHeader
Friend WithEvents Timer1 As Timer
End Class
From what I see in Designer code, TechDateList Height exceeds ListSplitter.Panel1 Height:
Me.ListSplitter.SplitterDistance = 25
Me.TechDateList.Size = New System.Drawing.Size(258, 166)
make sure that TechDateList fits Panel1 in Designer, e.g
Me.ListSplitter.SplitterDistance = 125
Me.TechDateList.Size = New System.Drawing.Size(258, 120)
and then resize will work as expected.
consider also docking TechDateList to Left - the list will get maximum possible Height and will resize with Panel1
I'm guessing that moving the splitter is resizing the ListView in Panel2 but not resizing the ListView in Panel1. I'm probably missing something simple somewhere. Regardless, if I add this code to the form, I get the desired results:
Private Sub ListSplitter_SplitterMoved(sender As Object, e As SplitterEventArgs) Handles ListSplitter.SplitterMoved
TechDateList.Height = ListSplitter.Panel1.Height
End Sub
Related
I want to use AutoSize of TableLayoutPanel and FlowLayoutPanel to layout my Controls. After the parent Control has been layed out I want to freeze the layout, so if I hide a control, nothing should collapse. So I want to use Control.Visible but without collapsing it.
Background information: I have a Control that supports multiple languages. I want the design to adjust to the language automatically. If I click a CheckBox then sometimes some Controls are hiding or showing, which causes the whole design to change if I use AutoSize. I don't want the Controls to collapse, I just want the Controls to show the background of the parent Control and keep the size.
Example (vb.net)
Form1.vb
Public Class Form1
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
Label1.Visible = CheckBox1.Checked
End Sub
End Class
Form1.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Wird vom Windows Form-Designer benötigt.
Private components As System.ComponentModel.IContainer
'Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich.
'Das Bearbeiten ist mit dem Windows Form-Designer möglich.
'Das Bearbeiten mit dem Code-Editor ist nicht möglich.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel()
Me.Label1 = New System.Windows.Forms.Label()
Me.CheckBox1 = New System.Windows.Forms.CheckBox()
Me.TableLayoutPanel1.SuspendLayout()
Me.SuspendLayout()
'
'TableLayoutPanel1
'
Me.TableLayoutPanel1.AutoSize = True
Me.TableLayoutPanel1.ColumnCount = 1
Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle())
Me.TableLayoutPanel1.Controls.Add(Me.Label1, 0, 0)
Me.TableLayoutPanel1.Controls.Add(Me.CheckBox1, 0, 1)
Me.TableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill
Me.TableLayoutPanel1.Location = New System.Drawing.Point(0, 0)
Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
Me.TableLayoutPanel1.RowCount = 2
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.Size = New System.Drawing.Size(800, 450)
Me.TableLayoutPanel1.TabIndex = 0
'
'Label1
'
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(3, 0)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(39, 13)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Label1"
'
'CheckBox1
'
Me.CheckBox1.AutoSize = True
Me.CheckBox1.Checked = True
Me.CheckBox1.CheckState = System.Windows.Forms.CheckState.Checked
Me.CheckBox1.Location = New System.Drawing.Point(3, 16)
Me.CheckBox1.Name = "CheckBox1"
Me.CheckBox1.Size = New System.Drawing.Size(81, 17)
Me.CheckBox1.TabIndex = 1
Me.CheckBox1.Text = "CheckBox1"
Me.CheckBox1.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.AutoSize = True
Me.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TableLayoutPanel1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.TableLayoutPanel1.ResumeLayout(False)
Me.TableLayoutPanel1.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TableLayoutPanel1 As TableLayoutPanel
Friend WithEvents Label1 As Label
Friend WithEvents CheckBox1 As CheckBox
End Class
Result:
I want the controls to not move around. I want the controls to keep the size if the label is hidden. The label should not collapse but paint the background of the parent control instead.
The best solution that I am sort of happy with is to write my own custom Panel that implements the desired behavior and put the target control into that custom Panel. The trick is to add a normal Panel to my custom Panel that hides the target control if Visible is changed to false.
Solution in VB.NET
NoCollapsePanel.vb
Public Class NoCollapsePanel
Public Enum VisibleModeE
Collapse
KeepSize
End Enum
Public Property VisibleMode As VisibleModeE
Get
Return _VisibleMode
End Get
Set
If Value = VisibleMode Then Return
_VisibleMode = Value
RefreshVisibility()
End Set
End Property
Private Sub RefreshVisibility()
If _Visible Then Controls.Remove(hidePanel)
Select Case VisibleMode
Case VisibleModeE.Collapse
MyBase.Visible = _Visible
Case VisibleModeE.KeepSize
MyBase.Visible = True
If Not Visible Then
' this is doing the trick
hidePanel.Size = Size
Controls.Add(hidePanel)
hidePanel.BringToFront()
End If
End Select
End Sub
Public Shadows Event VisibleChanged As EventHandler
Private ReadOnly hidePanel As New Panel() With {.Margin = New Padding(0)}
Private _Visible As Boolean = True
Private _VisibleMode As VisibleModeE = VisibleModeE.KeepSize
Public Overloads Property Visible As Boolean
Get
Return _Visible
End Get
Set
If _Visible = Value Then Return
_Visible = Value
RefreshVisibility()
RaiseEvent VisibleChanged(Me, New EventArgs())
End Set
End Property
Protected Overrides Sub OnResize(eventargs As EventArgs)
MyBase.OnResize(eventargs)
hidePanel.Size = Size
End Sub
End Class
NoCollapsePanel.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class NoCollapsePanel
Inherits System.Windows.Forms.Panel
'Das Steuerelement überschreibt den Löschvorgang zum Bereinigen der Komponentenliste.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Wird vom Steuerelement-Designer benötigt.
Private components As System.ComponentModel.IContainer
' Hinweis: Die folgende Prozedur ist für den Komponenten-Designer erforderlich.
' Sie kann mit dem Komponenten-Designer geändert werden. Das Bearbeiten mit
' dem Code-Editor ist nicht möglich.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
End Class
Testing the Panel
Form1.vb
Public Class Form1
Public Sub New()
' Dieser Aufruf ist für den Designer erforderlich.
InitializeComponent()
' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
ComboBox1.DataSource = System.Enum.GetValues(GetType(NoCollapsePanel.VisibleModeE))
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
NoCollapsePanel1.Visible = CheckBox1.Checked
End Sub
Private rnd As New Random
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
BackColor = Color.FromArgb(255, rnd.Next(255), rnd.Next(255), rnd.Next(255))
End Sub
Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
Label1.Text = If(CheckBox2.Checked, "some text", "some very very very very long text")
End Sub
Private Sub NoCollapsePanel1_VisibleChanged(sender As Object, e As EventArgs) Handles NoCollapsePanel1.VisibleChanged
TestVisibleChanged_Label.Text = DateTime.Now
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
NoCollapsePanel1.VisibleMode = ComboBox1.SelectedValue
End Sub
End Class
Form1.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Wird vom Windows Form-Designer benötigt.
Private components As System.ComponentModel.IContainer
'Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich.
'Das Bearbeiten ist mit dem Windows Form-Designer möglich.
'Das Bearbeiten mit dem Code-Editor ist nicht möglich.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel()
Me.CheckBox1 = New System.Windows.Forms.CheckBox()
Me.Button1 = New System.Windows.Forms.Button()
Me.CheckBox2 = New System.Windows.Forms.CheckBox()
Me.TestVisibleChanged_Label = New System.Windows.Forms.Label()
Me.FlowLayoutPanel2 = New System.Windows.Forms.FlowLayoutPanel()
Me.ComboBox1 = New System.Windows.Forms.ComboBox()
Me.NoCollapsePanel1 = New WindowsApp4.NoCollapsePanel()
Me.FlowLayoutPanel1 = New System.Windows.Forms.FlowLayoutPanel()
Me.Label1 = New System.Windows.Forms.Label()
Me.TableLayoutPanel1.SuspendLayout()
Me.FlowLayoutPanel2.SuspendLayout()
Me.NoCollapsePanel1.SuspendLayout()
Me.FlowLayoutPanel1.SuspendLayout()
Me.SuspendLayout()
'
'TableLayoutPanel1
'
Me.TableLayoutPanel1.AutoSize = True
Me.TableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.TableLayoutPanel1.ColumnCount = 1
Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle())
Me.TableLayoutPanel1.Controls.Add(Me.NoCollapsePanel1, 0, 0)
Me.TableLayoutPanel1.Controls.Add(Me.CheckBox1, 0, 1)
Me.TableLayoutPanel1.Controls.Add(Me.Button1, 0, 2)
Me.TableLayoutPanel1.Controls.Add(Me.CheckBox2, 0, 3)
Me.TableLayoutPanel1.Controls.Add(Me.TestVisibleChanged_Label, 0, 4)
Me.TableLayoutPanel1.Controls.Add(Me.ComboBox1, 0, 5)
Me.TableLayoutPanel1.Location = New System.Drawing.Point(3, 3)
Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
Me.TableLayoutPanel1.RowCount = 6
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel1.Size = New System.Drawing.Size(127, 134)
Me.TableLayoutPanel1.TabIndex = 1
'
'CheckBox1
'
Me.CheckBox1.AutoSize = True
Me.CheckBox1.Checked = True
Me.CheckBox1.CheckState = System.Windows.Forms.CheckState.Checked
Me.CheckBox1.Location = New System.Drawing.Point(3, 22)
Me.CheckBox1.Name = "CheckBox1"
Me.CheckBox1.Size = New System.Drawing.Size(83, 17)
Me.CheckBox1.TabIndex = 1
Me.CheckBox1.Text = "Show Panel"
Me.CheckBox1.UseVisualStyleBackColor = True
'
'Button1
'
Me.Button1.AutoSize = True
Me.Button1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.Button1.Location = New System.Drawing.Point(3, 45)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(106, 23)
Me.Button1.TabIndex = 2
Me.Button1.Text = "Change BackColor"
Me.Button1.UseVisualStyleBackColor = True
'
'CheckBox2
'
Me.CheckBox2.AutoSize = True
Me.CheckBox2.Location = New System.Drawing.Point(3, 74)
Me.CheckBox2.Name = "CheckBox2"
Me.CheckBox2.Size = New System.Drawing.Size(92, 17)
Me.CheckBox2.TabIndex = 3
Me.CheckBox2.Text = "Change Label"
Me.CheckBox2.UseVisualStyleBackColor = True
'
'TestVisibleChanged_Label
'
Me.TestVisibleChanged_Label.AutoSize = True
Me.TestVisibleChanged_Label.Location = New System.Drawing.Point(3, 94)
Me.TestVisibleChanged_Label.Name = "TestVisibleChanged_Label"
Me.TestVisibleChanged_Label.Size = New System.Drawing.Size(88, 13)
Me.TestVisibleChanged_Label.TabIndex = 4
Me.TestVisibleChanged_Label.Text = "Visibility changed"
'
'FlowLayoutPanel2
'
Me.FlowLayoutPanel2.AutoSize = True
Me.FlowLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.FlowLayoutPanel2.Controls.Add(Me.TableLayoutPanel1)
Me.FlowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill
Me.FlowLayoutPanel2.Location = New System.Drawing.Point(0, 0)
Me.FlowLayoutPanel2.Name = "FlowLayoutPanel2"
Me.FlowLayoutPanel2.Size = New System.Drawing.Size(800, 450)
Me.FlowLayoutPanel2.TabIndex = 2
'
'ComboBox1
'
Me.ComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.ComboBox1.FormattingEnabled = True
Me.ComboBox1.Location = New System.Drawing.Point(3, 110)
Me.ComboBox1.Name = "ComboBox1"
Me.ComboBox1.Size = New System.Drawing.Size(121, 21)
Me.ComboBox1.TabIndex = 5
'
'NoCollapsePanel1
'
Me.NoCollapsePanel1.AutoSize = True
Me.NoCollapsePanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.NoCollapsePanel1.Controls.Add(Me.FlowLayoutPanel1)
Me.NoCollapsePanel1.Location = New System.Drawing.Point(3, 3)
Me.NoCollapsePanel1.Name = "NoCollapsePanel1"
Me.NoCollapsePanel1.Size = New System.Drawing.Size(45, 13)
Me.NoCollapsePanel1.TabIndex = 0
Me.NoCollapsePanel1.VisibleMode = WindowsApp4.NoCollapsePanel.VisibleModeE.KeepSize
'
'FlowLayoutPanel1
'
Me.FlowLayoutPanel1.AutoSize = True
Me.FlowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.FlowLayoutPanel1.Controls.Add(Me.Label1)
Me.FlowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill
Me.FlowLayoutPanel1.Location = New System.Drawing.Point(0, 0)
Me.FlowLayoutPanel1.Name = "FlowLayoutPanel1"
Me.FlowLayoutPanel1.Size = New System.Drawing.Size(45, 13)
Me.FlowLayoutPanel1.TabIndex = 1
'
'Label1
'
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(3, 0)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(39, 13)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Label1"
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.AutoSize = True
Me.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.FlowLayoutPanel2)
Me.Name = "Form1"
Me.Text = "Form1"
Me.TableLayoutPanel1.ResumeLayout(False)
Me.TableLayoutPanel1.PerformLayout()
Me.FlowLayoutPanel2.ResumeLayout(False)
Me.FlowLayoutPanel2.PerformLayout()
Me.NoCollapsePanel1.ResumeLayout(False)
Me.NoCollapsePanel1.PerformLayout()
Me.FlowLayoutPanel1.ResumeLayout(False)
Me.FlowLayoutPanel1.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents NoCollapsePanel1 As NoCollapsePanel
Friend WithEvents Label1 As Label
Friend WithEvents FlowLayoutPanel1 As FlowLayoutPanel
Friend WithEvents TableLayoutPanel1 As TableLayoutPanel
Friend WithEvents CheckBox1 As CheckBox
Friend WithEvents FlowLayoutPanel2 As FlowLayoutPanel
Friend WithEvents Button1 As Button
Friend WithEvents CheckBox2 As CheckBox
Friend WithEvents TestVisibleChanged_Label As Label
Friend WithEvents ComboBox1 As ComboBox
End Class
I need to show ToolTip on a certain control for a certain period of time, with this code I get the ToolTip to show, but it won't disappear:
Public Sub tooltipControl(ByVal kontrola As Object, ByVal opened As Boolean, ByVal Optional poruka As String = "", ByVal Optional boja As Object = Nothing)
Dim ellipse1 As New Ellipse
ellipse1.Height = 25
ellipse1.Width = 50
ellipse1.Fill = Brushes.Gray
ellipse1.HorizontalAlignment = HorizontalAlignment.Left
Dim bubble As New ToolTip
bubble.PlacementTarget = kontrola
bubble.Placement = PlacementMode.Bottom
ToolTipService.SetShowDuration(kontrola, 5000)
Dim bdec As New BulletDecorator
Dim littleEllipse As New Ellipse
littleEllipse.Height = 20
littleEllipse.Width = 20
littleEllipse.Fill = boja
bdec.Bullet = littleEllipse
Dim tipText As New TextBlock
tipText.Text = poruka
bdec.Child = tipText
bubble.Content = bdec
bubble.IsOpen = True
kontrola.ToolTip = bubble
End Sub
Set the duration on the elemtent the tooltip belongs to
ToolTipService.SetShowDuration(kontrola, 5000)
and add the tooltip before opening it
kontrola.ToolTip = bubble
bubble.IsOpen = True
In a WPF project, using the following code to customize a button in the Window_Loaded event:
Dim style As Style = New Style
style.TargetType = GetType(Button)
Dim trigger As DataTrigger = New DataTrigger
trigger.Value = "OK"
'set binding
Dim bi As New Binding
Dim pp As New PropertyPath("Content")
bi.Path = pp
bi.RelativeSource = RelativeSource.Self
trigger.Binding = bi ' New Binding(pp.Path)
Dim setter As Setter = New Setter
setter.Property = Button.BackgroundProperty
setter.Value = Brushes.Red
trigger.Setters.Add(setter)
'clear the triggers
style.Triggers.Clear()
style.Triggers.Add(trigger)
btn_Step.Style = style
It compiles okay, but no noticeable change to the button. How can I get this to be applied?
I figured out how to do it with code - here's my final solution:
Public Function CreateStyle(ByVal clr1 As SolidColorBrush, ByVal clr2 As SolidColorBrush)
Dim st As New Style
st.TargetType = GetType(Button)
Dim se0 As New Setter
se0.Property = Button.OverridesDefaultStyleProperty
se0.Value = True
st.Setters.Add(se0)
Dim se1 As New Setter
se1.Property = TemplateProperty
Dim ct As New ControlTemplate
'Reference: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ddb7fd77-dea1-40f5-a5b7-30d35ecda70e/creating-a-control-template-with-code-behind?forum=wpf
ct.TargetType = GetType(Button)
Dim fef0 As New FrameworkElementFactory(GetType(Border))
fef0.Name = "Border"
fef0.SetValue(Border.BorderThicknessProperty, New Thickness(1))
fef0.SetValue(Border.BorderBrushProperty, Brushes.Black)
ct.VisualTree = fef0
Dim fef1 As New FrameworkElementFactory(GetType(ContentPresenter))
fef1.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center)
fef1.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center)
fef0.AppendChild(fef1)
Dim tr0 As New Trigger
tr0.Property = Button.IsMouseOverProperty
tr0.Value = True
Dim se2 As New Setter
se2.TargetName = "Border"
se2.Property = Button.BackgroundProperty
se2.Value = clr1
tr0.Setters.Add(se2)
ct.Triggers.Add(tr0)
Dim tr1 As New Trigger
tr1.Property = Button.IsMouseOverProperty
tr1.Value = False
Dim se3 As New Setter
se3.TargetName = "Border"
se3.Property = Button.BackgroundProperty
se3.Value = clr2
tr1.Setters.Add(se3)
ct.Triggers.Add(tr1)
se1.Value = ct
st.Setters.Add(se1)
Return st
End Function
We use ToggleEdit (to enable/disable controls) when navigating to a new page in a new tab. This time the new tab is created in an existing page. It works as it should the first time the grid is loaded, but then fails the second time. Have tried lots of different methods but still the same result
Double clicking a row in a DataGrid causes a new tab to be opened
Private Sub Alarm_Edit(sender As Object, e As RoutedEventArgs)
Try
e.Handled = True
IsNewRecord = False
Dim DGV As DGVx = PersonalSchedule_Grid.FindName("Schedule_AlarmsDGV")
If DGV.SelectedItems.Count = 1 Then
Dim row As System.Data.DataRowView = DGV.SelectedItems(0)
Alarm_ID = row("ID")
Dim vName As String = row("Subject")
Dim vTab As STC_Tabx = PersonalSchedule_Grid.FindName(TabName)
Dim TabControl As STCx = PersonalSchedule_Grid.FindName("Alarm_TabControl")
If Not vTab Is Nothing Then
vTab.Close()
End If
Dim MCFrame As New Frame
Dim MCTab As New STC_Tabx
With MCTab
.Name = TabName
.Header = " " & Left(vName, 20) & " "
.ImageSource = ReturnImageAsString("Edit.png", 16)
.CloseButtonVisibility = DevComponents.WpfEditors.eTabCloseButtonVisibility.Visible
.TabToolTip = "View or edit the " & vName & " record"
' .Content = MCFrame
.Content = AlarmGrid()
End With
RemoveHandler MCTab.Closing, AddressOf TabControl_TabClosing
AddHandler MCTab.Closing, AddressOf TabControl_TabClosing
RegisterControl(PersonalSchedule_Grid, MCTab)
TabControl.Items.Add(MCTab)
' MCFrame.NavigationService.Navigate(AlarmPage)
LoadedTabs(TabName)
MCTab.IsSelected = True
End If
Catch ex As Exception
EmailError(ex)
End Try
End Sub
... and this is added to the tab
Private Function AlarmGrid() As Grid
Try
Dim MainGrid As New Grid
MainGrid.Children.Clear()
Dim vGrid As New Grid
vGrid.ColumnDefinitions.Clear()
vGrid.RowDefinitions.Clear()
vGrid.Children.Clear()
Dim SV As New ScrollViewer
With SV
.Name = "Alarm_SV"
.Content = vGrid
.VerticalScrollBarVisibility = ScrollBarVisibility.Auto
End With '
RegisterControl(PersonalSchedule_Grid, SV)
MainGrid.Children.Add(SV)
For i As Integer = 0 To 5
Dim vRow As New RowDefinition
If i = 4 Then
vRow.Height = New GridLength(35, GridUnitType.Star)
Else
vRow.Height = New GridLength(35)
End If
vGrid.RowDefinitions.Add(vRow)
Next
For i As Integer = 0 To 1
Dim vCol As New ColumnDefinition
If i = 0 Then
vCol.Width = New GridLength(120)
ElseIf i = 1 Then
vCol.Width = New GridLength(200, GridUnitType.Star)
End If
vGrid.ColumnDefinitions.Add(vCol)
Next
'Date | Time | Subject | Details
Dim vToolBar As New ToolBar
Grid.SetColumn(vToolBar, 0)
Grid.SetColumnSpan(vToolBar, 2)
Grid.SetRow(vToolBar, 0)
vGrid.Children.Add(vToolBar)
Dim EditButton As New Button
With EditButton
.Content = ReturnToolBarImage("Edit.png")
.Name = "Alarm_EditButton"
.ToolTip = "Edit the record"
If IsNewRecord = True Then
.Visibility = Visibility.Collapsed
End If
End With
RegisterControl(PersonalSchedule_Grid, EditButton)
vToolBar.Items.Add(EditButton)
Dim EditTS As New Separator
With EditTS
.Name = "Alarm_EditTS"
If IsNewRecord = True Then
.Visibility = Visibility.Collapsed
End If
End With
RegisterControl(PersonalSchedule_Grid, EditTS)
vToolBar.Items.Add(EditTS)
Dim SaveUpdateButton As New Button
With SaveUpdateButton
.Name = "Alarm_SaveUpdateButton"
If IsNewRecord = True Then
.Content = ReturnToolBarImage("Record_Insert.png")
.ToolTip = "Save the record"
.IsEnabled = True
Else
.Content = ReturnToolBarImage("Record_Update.png")
.ToolTip = "Update the record"
.IsEnabled = False
End If
End With
RegisterControl(PersonalSchedule_Grid, SaveUpdateButton)
vToolBar.Items.Add(SaveUpdateButton)
vToolBar.Items.Add(TS_Separator)
Dim EnabledCB As New CBx
With EnabledCB
.Content = "Enabled"
.ToolTip = "The alarm is enabled"
.Name = "Alarm_EnabledCB"
.IsNewRecord = IsNewRecord
If IsNewRecord = True Then
.Visibility = Visibility.Collapsed
End If
End With
RegisterControl(PersonalSchedule_Grid, EnabledCB)
vToolBar.Items.Add(EnabledCB)
If IsNewRecord = False Then
vToolBar.Items.Add(TS_Separator)
End If
Dim DateLB As New TextLabel
With DateLB
.Text = "Date"
End With
Grid.SetColumn(DateLB, 0)
Grid.SetRow(DateLB, 1)
vGrid.Children.Add(DateLB)
Dim DateTB As New DateTBx
With DateTB
.IsNewRecord = IsNewRecord
.Value = Today
.Name = "Alarm_DateTB"
End With
RegisterControl(PersonalSchedule_Grid, DateTB)
Grid.SetColumn(DateTB, 1)
Grid.SetRow(DateTB, 1)
vGrid.Children.Add(DateTB)
Dim TimeLB As New TextLabel
With TimeLB
.Text = "Time"
End With
Grid.SetColumn(TimeLB, 0)
Grid.SetRow(TimeLB, 2)
vGrid.Children.Add(TimeLB)
Dim TimeTB As New TimeTBx
With TimeTB
.Value = Format(DateTime.Now, "HH:mm")
.IsNewRecord = IsNewRecord
.Name = "Alarm_TimeTB"
End With
RegisterControl(PersonalSchedule_Grid, TimeTB)
Grid.SetColumn(TimeTB, 1)
Grid.SetRow(TimeTB, 2)
vGrid.Children.Add(TimeTB)
Dim SubjectLB As New TextLabel
With SubjectLB
.Text = "Subject"
End With
Grid.SetColumn(SubjectLB, 0)
Grid.SetRow(SubjectLB, 3)
vGrid.Children.Add(SubjectLB)
Dim SubjectTB As New TBx
With SubjectTB
.Width = 300
.IsNewRecord = IsNewRecord
.Name = "Alarm_SubjectTB"
End With
RegisterControl(PersonalSchedule_Grid, SubjectTB)
Grid.SetColumn(SubjectTB, 1)
Grid.SetRow(SubjectTB, 3)
vGrid.Children.Add(SubjectTB)
Dim DetailsLB As New TextBlock
With DetailsLB
.Text = "Details"
.VerticalAlignment = VerticalAlignment.Top
.HorizontalAlignment = Windows.HorizontalAlignment.Left
.Margin = New Thickness(10, 10, 0, 0)
End With
Grid.SetColumn(DetailsLB, 0)
Grid.SetRow(DetailsLB, 4)
vGrid.Children.Add(DetailsLB)
Dim DetailsTB As New MultiLineLargeTBx
With DetailsTB
.Name = "Alarm_DetailsTB"
.IsNewRecord = IsNewRecord
End With
RegisterControl(PersonalSchedule_Grid, DetailsTB)
Grid.SetColumn(DetailsTB, 1)
Grid.SetRow(DetailsTB, 4)
vGrid.Children.Add(DetailsTB)
If IsNewRecord = False Then
Dim vTime As TimeSpan = Nothing
Dim vDate As Date = Nothing
Dim vSubject As String = ""
Dim vDetails As String = ""
Dim IsAlarmSet As Boolean = False
Using vService As New Service1Client
strSQL = "Select Alarm_Date, Alarm_Time, Alarm_Subject, Alarm_Content, Alarm_Set FROM Alarm_Info WHERE Alarm_ID = " & Alarm_ID
Using DS As DataSet = vService.ReturnDataSetHAS(strSQL)
For Each Row As DataRow In DS.Tables(0).Rows
vTime = Row("Alarm_Time")
vDate = LocalDateFormat(Row("Alarm_Date"))
vSubject = ReturnText(Row("Alarm_Subject"))
vDetails = ReturnText(Row("Alarm_Content"))
Dim AlarmSet As Integer = Row("Alarm_Set")
If AlarmSet = 1 Then
IsAlarmSet = True
End If
Next
End Using
End Using
Dim TimeString As String = ReturnFormattedTime(vTime, False, True)
TimeTB.Value = TimeString
DateTB.Value = vDate
SubjectTB.Text = vSubject
DetailsTB.Text = vSubject
EnabledCB.IsChecked = IsAlarmSet
RemoveHandler EditButton.Click, AddressOf ToggleEdit_Click
RemoveHandler SV.MouseDoubleClick, AddressOf ToggleEdit_Click
RemoveHandler SaveUpdateButton.Click, AddressOf DB_Update
AddHandler EditButton.Click, AddressOf ToggleEdit_Click
AddHandler SV.MouseDoubleClick, AddressOf ToggleEdit_Click
AddHandler SaveUpdateButton.Click, AddressOf DB_Update
Else
RemoveHandler SaveUpdateButton.Click, AddressOf DB_Insert
AddHandler SaveUpdateButton.Click, AddressOf DB_Insert
End If
Return MainGrid
Catch ex As Exception
EmailError(ex)
Return Nothing
End Try
End Function
...and clicking the edit button or double clicking the ScrollViewer causes this to run
Private Sub ToggleEdit_Click(sender As Object, e As RoutedEventArgs)
Try
ToggleEdit()
Catch ex As Exception
EmailError(ex)
End Try
End Sub
Private Sub ToggleEdit()
Try
Dim SV As ScrollViewer = PersonalSchedule_Grid.FindName("Alarm_SV")
Dim DateTB As DateTBx = PersonalSchedule_Grid.FindName("Alarm_DateTB")
Dim TimeTB As TimeTBx = PersonalSchedule_Grid.FindName("Alarm_TimeTB")
Dim SubjectTB As TBx = PersonalSchedule_Grid.FindName("Alarm_SubjectTB")
Dim DetailsTB As MultiLineLargeTBx = PersonalSchedule_Grid.FindName("Alarm_DetailsTB")
Dim EnabledCB As CBx = PersonalSchedule_Grid.FindName("Alarm_EnabledCB")
Dim UpdateButton As Button = PersonalSchedule_Grid.FindName("Alarm_SaveUpdateButton")
If UpdateButton.IsEnabled = False Then
UpdateButton.IsEnabled = True
DateTB.IsNewRecord = True
TimeTB.IsNewRecord = True
SubjectTB.IsNewRecord = True
DetailsTB.IsNewRecord = True
EnabledCB.IsNewRecord = True
Else
UpdateButton.IsEnabled = False
DateTB.IsNewRecord = False
TimeTB.IsNewRecord = False
SubjectTB.IsNewRecord = False
DetailsTB.IsNewRecord = False
EnabledCB.IsNewRecord = False
End If
Catch ex As Exception
EmailError(ex)
End Try
End Sub
That should change the update button .IsEnabled to true (and the other controls .IsReadOnly) and back to false if clicked again.
It must be something very basic about WPF that I have missed for years, but running through the code in debug everything is firing as it should - it's changing the value of the control but it's not reflecting in the UI. Tried UpdateLayout and a host of other possible solutions, but...
Any pointers would be really helpful
Thanks
Just discovered what is causing a HTML editor to throw the toys out when using a certain letter on a keyboard...
On the same page there are textboxes that contain things like html page name, title, navigate URL, menu text.... If one of the textboxes contains text with an underscore (say 'Test_Page') then the letter 'P' will not function in the HTML editor. I'm guessing (and could be way off base here as I didn't think textbox.txt could do this unlike Label.content) that WPF is taking the text entry and using it as a mnemonic key.. I do know that setting RecognisesAccessKey to false might cure it, but can't find a way to add that property or access ContentPresenter...
This is the class that I use to create the control and ideally would like to set it here
Public Class TBx
Inherits TextBox
Public Shared IsNewRecordProperty As DependencyProperty = DependencyProperty.Register("IsNewRecord", GetType(Boolean), GetType(TBx), New PropertyMetadata(New PropertyChangedCallback(AddressOf IsNewRecordChanged)))
Public Property IsNewRecord As Boolean
Get
Return GetValue(IsNewRecordProperty)
End Get
Set(value As Boolean)
SetValue(IsNewRecordProperty, value)
End Set
End Property
Protected Overrides Sub OnInitialized(e As System.EventArgs)
MyBase.OnInitialized(e)
VerticalAlignment = Windows.VerticalAlignment.Center
HorizontalAlignment = Windows.HorizontalAlignment.Left
BorderBrush = New SolidColorBrush(Colors.Silver)
Height = 22
SpellCheck.IsEnabled = True
UndoLimit = 0
If IsNewRecord = True Then
BorderThickness = New Thickness(1)
IsReadOnly = False
Background = New SolidColorBrush(Colors.White)
Else
BorderThickness = New Thickness(0)
IsReadOnly = True
Background = New SolidColorBrush(Colors.Transparent)
End If
End Sub
Private Shared Sub IsNewRecordChanged(sender As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim vControl As TBx = TryCast(sender, TBx)
Dim vBoolean As Boolean = e.NewValue
If vBoolean = True Then
vControl.BorderThickness = New Thickness(1)
vControl.IsReadOnly = False
vControl.Background = New SolidColorBrush(Colors.White)
Else
vControl.BorderThickness = New Thickness(0)
vControl.IsReadOnly = True
vControl.Background = New SolidColorBrush(Colors.Transparent)
End If
End Sub
End Class
Thank you
Couldn't find an easy way to do this from the class, but this works on the page
Dim CP As New ContentPresenter
CP.RecognizesAccessKey = False
Then add the TextBox to the ContentPresenter
Case 1
vLabel.Text = "Page Name"
With vTB
.Width = 200
.Name = vName & "PageNameTB"
.ToolTip = "This is the short name for the page"
.IsNewRecord = IsNewRecord
End With
CP.Content = vTB
The add the CP to the grid
RegisterControl(SecurePage_Grid, vTB)
Grid.SetColumn(vLabel, 0)
Grid.SetRow(vLabel, i)
If i = 1 Then
Grid.SetRow(CP, i)
Grid.SetColumn(CP, 1)
Else
Grid.SetRow(vTB, i)
Grid.SetColumn(vTB, 1)
End If
vGrid.Children.Add(vLabel)
If i = 1 Then
vGrid.Children.Add(CP)
Else
vGrid.Children.Add(vTB)
End If