POSH:变量或填充变量上的新事件

时间:2014-06-27 10:19:30

标签: powershell powershell-v3.0

我喜欢在填充/更改变量或具有定义值时触发事件。 其中一种可能吗?

我有一个连接到Serial的条形码扫描器在不同的运行空间中运行。 并创建了一个同步哈希表来共享条形码。

我想在hashtable.Value包含条形码时触发事件 所以我可以将它添加到GUI而不会阻塞当前线程。

(我知道我可以每隔100毫秒制作一个System.Timers.Timer对象,但我宁愿使用一个事件。)

2 个答案:

答案 0 :(得分:1)

只是一个想法,但你可以尝试添加一个脚本方法到你的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
}

答案 1 :(得分:1)

在不知道如何组成UI的情况下,此示例相当基本,但展示了如何使用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)