2014-06-27 59 views
0

我喜歡在變量填充/更改或具有定義值時觸發事件。 其中一個可能嗎?POSH:變量上的新事件已更改或已填充

我有一個條碼掃描器連接到串行運行在不同的運行空間。 並創建了一個同步散列表來共享條形碼。

我想觸發一個事件,當hashtable.Value包含條形碼 所以我可以將它添加到GUI而不會阻止當前線程。

(我知道我可以做一個System.Timers.Timer對象EN調查每100ms),但我寧願使用一個事件。)

回答

1

不知道你的用戶界面是如何構成的,這個例子是相當基本的,但顯示瞭如何使用一個ObservableCollection與一個列表框綁定自動更新列表框,只要有東西被添加到集合(甚至從另一個運行空間)。

$uiHash = [hashtable]::Synchronized(@{}) 
$uiHash.ObservableCollection = $Script:observableCollection = New-Object System.Collections.ObjectModel.ObservableCollection[string] 
$runspaceHash = [hashtable]::Synchronized(@{}) 
$newRunspace =[runspacefactory]::CreateRunspace() 
$newRunspace.ApartmentState = "STA" 
$newRunspace.ThreadOptions = "ReuseThread"   
$newRunspace.Open() 
$newRunspace.SessionStateProxy.SetVariable("uiHash",$uiHash)   
$newRunspace.SessionStateProxy.SetVariable("runspaceHash",$runspaceHash) 
$psCmd = [PowerShell]::Create().AddScript({ 
#Build the GUI 
[xml]$xaml = @" 
<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen" 
    Width = "313" Height = "800" ShowInTaskbar = "True" Background = "lightgray"> 
    <ScrollViewer VerticalScrollBarVisibility="Auto"> 
     <StackPanel > 
      <TextBox IsReadOnly="True" TextWrapping="Wrap"> 
       Type something and click Add 
      </TextBox> 
      <TextBox x:Name = "inputbox"/> 
      <Button x:Name="button1" Content="Add"/> 
      <Button x:Name="button2" Content="Remove"/> 
      <Expander IsExpanded="True"> 
       <ListBox x:Name="listbox" SelectionMode="Extended" /> 
      </Expander > 
     </StackPanel> 
    </ScrollViewer > 
</Window> 
"@ 

$reader=(New-Object System.Xml.XmlNodeReader $xaml) 
$uiHash.Window=[Windows.Markup.XamlReader]::Load($reader) 
  
#Connect to Controls 
$uiHash.inputbox = $uiHash.Window.FindName('inputbox') 
$uiHash.button1 = $uiHash.Window.FindName('button1') 
$uiHash.button2 = $uiHash.Window.FindName('button2') 
$uiHash.listbox = $uiHash.Window.FindName('listbox') 

$uiHash.Window.Add_SourceInitialized({ 
    #Have to have something initially in the collection 
    $uiHash.listbox.ItemsSource = $UIhash.observableCollection 
    $uiHash.inputbox.Focus() 
}) 
  
#Events 
$uiHash.button1.Add_Click({ 
    $UIhash.observableCollection.Add($uiHash.inputbox.text) 
    $uiHash.inputbox.Clear() 
}) 
$uiHash.button2.Add_Click({ 
    ForEach ($item in @($uiHash.listbox.SelectedItems)) { 
     $UIhash.observableCollection.Remove($item) 
    } 
})  
$uiHash.Window.ShowDialog() | Out-Null 
}) 
$psCmd.Runspace = $newRunspace 
$Handle = $psCmd.BeginInvoke() 

隨着窗口打開,您現在可以通過窗口上的Dispatcher將數據發送到observablecollecton。每次更新集合時,列表框都將以相同的方式更新(添加,刪除或清除)。

# While form is open, you can send data to the form by updating the observablecollection 
# This has to be done on the UI thread though! 
$uiHash.Window.Dispatcher.Invoke('Normal',[Action]{ 
    $UIhash.observableCollection.Add(1) 
}) 

下面添加的代碼只是爲了確保在本示例中關閉表單後所有內容都已處理完畢。

# Once form has closed, make sure to dispose of everything 
$psCmd.EndInvoke($Handle) 
1

只是一個想法,但你可以嘗試添加scriptmethod您hastable該檢查值是條形碼,並且做一些事情之前,調用add()方法:

$instance = @{} 

add-member -Force -in $instance scriptmethod MyAdd { 
    param([string]$bar = "bar", [string]$foo = "foo" ) 

    #pseudo code 
    if ($foo is barcode) { do this stuff in the gui } 
    #end of pseudo code 

    $this.add($bar,$foo) # call the native hastable add method 
}