2014-06-27 58 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 
}