winformspowershelltabsanchorpoint

Powershell/Forms - how to anchor listview within a tab control?


I'm trying to anchor a listview within a tab page in Forms, such that the listview resizes along with the tab and the other controls are also anchored to allow this, but it looks like it's anchoring to the parent form, not the tab - example code:

Add-Type -AssemblyName System.Windows.Forms
#
$form = New-Object System.Windows.Forms.Form
$form.MinimumSize = '585,700'
$form.StartPosition = 'CenterScreen'
$form.MaximizeBox = $false
$form.CancelButton = $ExitButton
#Autoscaling settings
$form.AutoScale = $true
$form.AutoScaleMode = "Font"
$ASsize = New-Object System.Drawing.SizeF(7,15)
$form.AutoScaleDimensions = $ASsize
#
#
$MainTab = New-Object System.Windows.Forms.TabControl
$MainTab.Size = '540,465'
$MainTab.Location = '15,95'
$MainTab.Multiline = $True
$MainTab.Name = 'TabPage'
$MainTab.SelectedIndex = 0
$MainTab.Anchor = 'Top,Left,Bottom,Right'
#
$TabPage1 = New-Object System.Windows.Forms.TabPage
$Tabpage1.Name = 'TabPage1'
$Tabpage1.Padding = '5,5,5,5'
$Tabpage1.TabIndex = 1
$Tabpage1.Text = 'Host SSH'
$Tabpage1.UseVisualStyleBackColor = $True
$TabPage1.Enabled = $false
#
$ESXhostList = New-Object System.Windows.Forms.ListView
$ESXhostList.View = [System.Windows.Forms.View]::Details
$ESXhostList.Location = '10,15'
$ESXhostList.Size = '510,150'
$ESXhostList.Columns.Add('Host Name',420) | Out-Null
$ESXhostList.Columns.Add('SSH Status',80) | Out-Null
$ESXhostList.Anchor = 'Top,Left,Right'
#
$ConnectBtn = New-Object System.Windows.Forms.Button
$ConnectBtn.Location = '20,190'
$ConnectBtn.Size = '54,24'
$ConnectBtn.Text = 'Connect'
$ConnectBtn.BackgroundImageLayout = 'Center'
$ConnectBtn.Enabled = $true
$ConnectBtn.Anchor = 'Left,Bottom'
#
$TabPage1.Controls.AddRange(@($ESXhostList,$ConnectBtn))
################################################################################
# TabPage 2
################################################################################
$TabPage2 = New-Object System.Windows.Forms.TabPage
$Tabpage2.Name = 'TabPage2'
$Tabpage2.Padding = '5,5,5,5'
$Tabpage2.TabIndex = 2
$Tabpage2.Text = 'Datastores'
$Tabpage2.UseVisualStyleBackColor = $True
$TabPage2.Enabled = $false
#
$DSList = New-Object System.Windows.Forms.ListView
$DSList.View = [System.Windows.Forms.View]::Details
$DSList.Location ='10,15'
$DSList.Size = '510,150'
$DSList.Columns.Add('Name',160) | Out-Null
$DSList.Columns.Add('FreeGB',65) | Out-Null
#
$ConnectBtn2 = New-Object System.Windows.Forms.Button
$ConnectBtn2.Location = '20,190'
$ConnectBtn2.Size = '54,24'
$ConnectBtn2.Text = 'Connect'
$ConnectBtn2.BackgroundImageLayout = 'Center'
$ConnectBtn2.Enabled = $true
#
$TabPage2.Controls.AddRange(@($DSList,$ConnectBtn2))
#
#
$MainTab.Controls.AddRange(@($TabPage1,$TabPage2))
#
# Info/Logging Window
$ProgressLog = New-Object System.Windows.Forms.TextBox
$ProgressLog.Location = '15,570'
$ProgressLog.Size = '540,80'
$ProgressLog.Multiline = $true
$ProgressLog.Anchor = 'Left,Bottom,Right'
$ProgressLog.TabStop = $false
$ProgressLog.ScrollBars = "Vertical"
$ProgressLog.ReadOnly = $true
#
# Add all the Form controls
$form.Controls.AddRange(@($MainTab,$ProgressLog))
#
#End
# Show form
$form.ShowDialog() | Out-Null
$form.Dispose()

In the above example, the only difference between the tabs is that I'm trying to anchor the listview and button controls in the first tab but there's no anchoring in the second tab.

Here's Tab 1 - the listview is outside the bounds of the tab instead of being anchored within it and the button is completely off the tab area

Incorrect anchoring

Here's the identical Tab 2 with no anchoring. Correct layout but no anchoring therefore resizing form does not resize the listview or reposition the button:

Correct layout but no anchoring therefore resizing form not working

Can anyone explain how to do this, as everything I read says that anchoring the tab then anchoring controls within it should work?


Solution

  • The reason it is not working has to do with the order you add controls to the control collection. You are adding your ListView and Button before adding the TabPage. The ListView then does not have any information on the width of the TabPage. The Anchor Parameter will then cause trouble since it is based on local coordinates within the TabPage.

    You either add each control object right after the parameters are set:

    $MainTab.Controls.Add($TabPage1)
    

    Or if you want to keep your array and add them at once you'll have to move your $TabPage2 Parameters right after the $TabPage1 Parameters and then add them both together right away before any other controls:

    $MainTab.Controls.AddRange(@($TabPage1,$TabPage2))
    

    Additionally your TabControl needs the local coordinates reset to the top-left corner of the Tab or else the the Anchor will position your objects on the invisible position grid.

    This is why you had the following problem:

    TabPage1 controls now reposition/resize but I had to use some really funky location and size values:

    Add the following Parameter to $MainTab to fix this:

    $MainTab.AutoSize = $true