本週 Windows PowerShell 秘訣

Office Space

這是使用 Windows PowerShell 的快速秘訣。只要有新的秘訣,我們每週就會在這裡發佈。如果您想要分享任何秘訣,或有任何疑問,請讓我們知道

您可以在本週 Windows PowerShell 秘訣封存找到更多秘訣。

複選清單方塊 -- 及其他事項!

好消息:您現在可以放鬆一下,因為偉大的日子終於來臨了。

上一週的秘訣中,我們解釋您該如何使用 Windows PowerShell 與 .NET Framework,建立可讓使用者在清單方塊進行選擇的對話方塊。在介紹建立我們承諾的清單方塊的基本觀念之後,我們將在本週秘訣中告訴您一些清理清單方塊的其他事項;其中最重要的是我們承諾告訴您如何建立複選清單方塊。那很可能是個錯誤;畢竟你們許多人上週寢食難安是無庸置疑的,不耐煩地等待我們告訴您如何整理清單方塊的時刻。好吧!現在您可以鬆一口氣了:基本清單方塊以外事項的講解時間終於到了。

馬上開始告訴您建立複選清單方塊的程式碼 (換句話說,可讓您同時選取多個項目的清單方塊)。我們今天不是要說明程式碼的每個細節;那些資料請參閱上一週秘訣。但是請勿擔心:我們「將」說明標準清單方塊與複選清單方塊之間的差異。

畢竟,如果不這樣做,我們也將會寢食難安。

但第一件事是:

$x = @()

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 

$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "Data Entry Form"
$objForm.Size = New-Object System.Drawing.Size(300,200) 
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True

$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
    {
foreach ($objItem in $objListbox.SelectedItems)
{$x += $objItem}
$objForm.Close()
    }
    })

$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
{$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"

$OKButton.Add_Click(
   {
foreach ($objItem in $objListbox.SelectedItems)
{$x += $objItem}
$objForm.Close()
   })

$objForm.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Please make a selection from the list below:"
$objForm.Controls.Add($objLabel) 

$objListbox = New-Object System.Windows.Forms.Listbox 
$objListbox.Location = New-Object System.Drawing.Size(10,40) 
$objListbox.Size = New-Object System.Drawing.Size(260,20) 

$objListbox.SelectionMode = "MultiExtended"

[void] $objListbox.Items.Add("Item 1")
[void] $objListbox.Items.Add("Item 2")
[void] $objListbox.Items.Add("Item 3")
[void] $objListbox.Items.Add("Item 4")
[void] $objListbox.Items.Add("Item 5")

$objListbox.Height = 70
$objForm.Controls.Add($objListbox) 
$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

$x

很有趣的是,標準清單方塊與複選清單方塊之間真正不同的地方只有二個:1) 在複選清單方塊中,您必須指定 SelectionMode 屬性的值;2) 在複選清單方塊中,您必須處理選取項目的陣列,而不是單一選取項目。不論您是否相信,這就是將標準清單方塊轉換成複選清單方塊的全部內容。

讓我們就從指定 SelectionMode 的屬性值開始:

$objListbox.SelectionMode = "MultiExtended"

如您所見,這並非您必須執行的最複雜編碼。在此情況下,我們已經將 SelectionMode 設定為 MultiExtended。什麼意思?某方面而言,它表示您可以在清單方塊中選取多個項目;您唯一必須做的是按一個項目,然後按住 Ctrl 鍵再按其他項目。(另一個項目以及另一個項目...)此外,您也可以按一個項目,按住 Shift 鍵後再按第二個項目;這樣會選取這兩個項目及其間的任何項目。例如,假設我們的清單方塊 (我們所做) 如下:

Ff730950.listbox2a2(zh-tw,TechNet.10).jpg

現在,在 MultiExtended 模式下,假設您按一下 [Item 1] (項目 1),然後按住 Shift 鍵再按 [Item 4] (項目 4)。會發生什麼事呢?這是即將發生的事:

Ff730950.listbox2b(zh-tw,TechNet.10).jpg

不錯吧?

或者,您可以將 SelectionMode 設定為 MultiSimple。在此情況下,按住 Shift 鍵不會選取項目範圍。在該模式下,Shift 鍵的功能就像 Ctrl 鍵一樣:可讓您選取另一個項目。下面是在 MultiSimple 模式下按 [Item 1] (項目 1) 後按住 Shift 鍵,再選取 [Item 4] (項目 4) 時所得到的結果:

Ff730950.listbox2c(zh-tw,TechNet.10).jpg

這樣是比較好或是更糟?事實上都不是;它只是不一樣而已。

如果您一點都「不想要」複選清單方塊;如果您只要平實簡單、只選取一個項目的清單方塊又該如何呢?那很簡單:只要不去設定 SelectionMode 就好了。

順便一提,在 MultiExtended 模式下,您也可以使用方向鍵 (同時按住或不按 Shift 鍵) 來選取清單方塊中的項目。您自己試試看。

現在,判斷清單方塊中選取哪些項目的程式碼該怎麼處理呢?上一週,我們談到標準清單方塊,我們抓取所選項目的值後,關閉對話方塊的程式碼,不會比下面的程式碼複雜:

$OKButton.Add_Click({$x=$objListbox.SelectedItem;$objForm.Close()})

那很簡單,因為我們不必處理清單方塊中的多個項目。不過,若使用複選清單方塊,我們就可以選取「多」個項目。我們如何處理「多個項目」呢?

以下是其中一種方式:

$OKButton.Add_Click(
   {
foreach ($objItem in $objListbox.SelectedItems)
{$x += $objItem}
$objForm.Close()
   })

說明這段程式碼如何運作之前,我們應該在指令碼的第一行指出我們要建立空白的陣列 $x:

$x = @()

為何要這樣做?因為我們需要空間來儲存清單方塊中所選取的項目,而陣列似乎是一個不錯的地方。

技術上來說那不是真的:我們不是「真正」需要空間來儲存清單方塊中選取的所有項目;這樣做可以輕鬆地處理屬性值 $objListbox.SelectedItems。因為陣列可讓人更容易想像此程序的運作方式,所以我們選擇使用陣列。

至於我們的小程式碼區塊,會從建立 foreach 迴圈開始,針對所有項目遞迴 SelectedItems 屬性 (如同其名稱所暗示,它是個多值屬性,其中包含在清單方塊選取的每個項目):

foreach ($objItem in $objListbox.SelectedItems)

然後,我們在此迴圈中使用下面這行程式碼,將每個項目加入陣列 $x:

$x += $objItem

一旦迴圈完成所有已選取的項目後,就呼叫 Close 方法來關閉表單。表單關閉之後,我們立即回傳 $x 的值。也就是指令碼中最後一行的內容:

$x

假設我們在清單方塊中選取項目 1、3 以及 4。在此情況下,我們應該可以得到下列結果:

Item 1
Item 3
Item 4

順便一提,您也可以在標準清單方塊使用相同的方法;唯一的不同是 SelectedItems 屬性不會擁有多個值。全憑個人喜好。

以上就是為您介紹的:複選清單方塊。現在就來整理清單方塊如何?

老實說,整理清單方塊並非您可做的唯一事情。(就此而言,您可能需要使用核取的清單方塊或清單檢視,在未來的秘訣中我們將涵蓋這兩個項目。)不過,您「可」做的一件事,就是指定每次顯示清單方塊時,自動選取的預設項目。 例如,假設我們想要 Item 2 (項目 2) 作為預設項目。那沒問題;下面這行程式碼將會為我們服務。只要在新增所有項目到清單方塊之後,將此段程式碼放入指令碼中:

$objListBox.SelectedItem = "Item 2"

現在執行指令碼並顯示清單方塊。您應該看到:

Ff730950.listbox2d(zh-tw,TechNet.10).jpg

還不賴吧?

另一個您可能會覺得有用的屬性是 Sorted 屬性。在建立清單方塊時,我們依英數字順序提供所有的清單項目:

[void] $objListbox.Items.Add("Item 1")
[void] $objListbox.Items.Add("Item 2")
[void] $objListbox.Items.Add("Item 3")
[void] $objListbox.Items.Add("Item 4")
[void] $objListbox.Items.Add("Item 5")

這樣很好,但是某些時候就不一定這麼順利;例如,如果您從文字檔取出資訊,就不保證該資訊會依英數字順序排列。若您需要的話,可以在將那些值加入清單方塊之前,使用 Sort-Object cmdlet 將它們排序。或者,您可以將 Sorted 屬性設定為 True,然後讓清單方塊為您處理這些事:

$objListBox.Sorted = $True

假設我們已經使用這塊程式碼將項目加入清單方塊中,其中區塊的項目「未」依英數字順序排序:

[void] $objListbox.Items.Add("Item 5")
[void] $objListbox.Items.Add("Item 2")
[void] $objListbox.Items.Add("Item 4")
[void] $objListbox.Items.Add("Item 1")
[void] $objListbox.Items.Add("Item 3")

什麼意思?那表示我們的清單方塊是反映加入那些項目的順序:

Ff730950.listbox2e(zh-tw,TechNet.10).jpg

好吧!那看起來不太順眼,不是嗎?不過,沒關係;請注意我們將 Sorted 屬性設定為 True 的差異:

Ff730950.listbox2a(zh-tw,TechNet.10).jpg

酷!

最後 (可能是至少) 可以變更清單方塊的前景和背景顏色,以及用來顯示每個項目的字型。您曾經「想要」這樣做嗎?好吧!那全憑個人喜好。不過,如果您「有」興趣,下面這些程式碼應該有所幫助:

$objListBox.BackColor = "cyan"
$objListBox.Forecolor = "blue"
$objListBox.Font = "Arial Black"

這是產生的對話方塊:

Ff730950.listbox2f(zh-tw,TechNet.10).jpg

就像我們說的,我們讓您全憑個人喜好來判斷是否值得這樣做。

以上本週的全部內容,大伙兒下週見。下週將呈現什麼秘訣呢?好吧!我們將展示一些真的很酷的事,我們將要 -- 您知道的:最好現在還是不要說太多。畢竟,本週您需要更多睡眠。

顯示: