第一个信息,我还没有使用C#!
我最近开始在PowerShell中编程GUI,并在两周前从WinForm切换到WPF。现在,我有一个简单的问题,因此没有教程甚至不愿宣布。
如何重新获得在GUI中执行的操作的信息? 有很多教程如何绑定数据,以便将其显示在GUI中。但是现在我想以其他方式使用它:
到目前为止,我的数据上下文定义为:
$DataContext = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
并添加了一些变量
$DataContext.Add($A.VMs)
$DataContext.Add($A.VM)
.
.
.
更糟糕的是,我尝试使用本教程https://learn-powershell.net/2012/10/14/powershell-and-wpf-writing-data-to-a-ui-from-a-different-runspace/
在应仅用于处理我的GUI的额外线程中使用它向文本框添加第二个绑定效果不佳。甚至没有多重绑定:
<TextBox.Text>
<MultiBinding StringFormat="{}{0}">
<Binding Path="SelectedItem" ElementName ="ListBoxVM" Mode="OneWay" />
<Binding Path="[1]" Mode="OneWayToSource" />
</MultiBinding>
</TextBox.Text>
我的下一个想法是在后面的代码中向datacontext [1]添加绑定,以将其绑定到TextBox.Text。但是,在此设置中,datacontext没有可以绑定的属性。
编辑:有人要求我提供更多代码,所以来了:
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms,System.Collections
# Creating Hashtable as base for Multithreading
$A = [hashtable]::Synchronized(@{})
# Here is the scriptblock for the Thread containing my XAML
$GUILayerScript = {
[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="VM Manager" WindowStartupLocation = "CenterScreen" Language ="de-de"
SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "Azure" ResizeMode = "NoResize" >
<StackPanel x:Name = "StackHorz" Margin = "5" Orientation = "Horizontal" >
<StackPanel x:Name = "StackLinks" Margin = "0,0,5,0" >
<Button x:Name = "LoginButton" ToolTip = "Benutzer wechseln">
<WrapPanel>
<TextBlock Text = "Logged in as: " />
<TextBlock x:Name ="LoginButtonText" Text = "{Binding Path=[5]}"/>
</WrapPanel>
</Button>
<ListBox x:Name = "ListBoxVM" ItemsSource = "{Binding Path=[0]}" ToolTip = "VM auswählen" MinHeight = "150" MinWidth = "100" Margin = "0,5,0,5" />
<Button x:Name = "ButtonVMRefresh" Content ="Aktualisieren" ToolTip = "Aktualisiert die Anzeige aller VMs" />
</StackPanel>
<StackPanel x:Name = "StackRechts" >
<Grid x:Name = "Grid" MinHeight = "220" MinWidth = "150" Background="azure" Margin = "0,0,0,5" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
</Grid.RowDefinitions>
<Label Content = "Chosen VM:" Grid.Column = "0" Grid.Row = "0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBox x:Name = "VMChoiceText" Grid.Column = "0" Grid.Row = "1" Height = "Auto" ToolTip = "Die aktuell Ausgewählte VM" IsReadOnly = "True" Margin = "10">
<TextBox.Text>
<MultiBinding StringFormat="{}{0}">
<Binding Path="SelectedItem" ElementName ="ListBoxVM" Mode="OneWay" />
<Binding Path="[1]" Mode="OneWayToSource" />
</MultiBinding>
</TextBox.Text>
</TextBox>
<Label Content = "Status:" Grid.Column = "0" Grid.Row = "2" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBox x:Name = "StatusText" Grid.Column = "0" Grid.Row = "3" Height = "Auto" ToolTip = "Status der VM" IsReadOnly = "True" Margin = "10,5,10,15"/>
<Button x:Name ="ButtonVMStart" Content = "VM start" Grid.Column = "0" Grid.Row = "4" ToolTip ="Startet die ausgewähle VM" Margin = "10"/>
<Button x:Name ="ButtonVMStop" Content = "VM stop" Grid.Column = "0" Grid.Row = "5" ToolTip ="Fährt die ausgewähle VM herunter" Margin = "10"/>
</Grid>
<TextBlock x:Name="TextBoxConsole" Height = "75" Background = "darkblue" Foreground = "white" />
</StackPanel>
</StackPanel>
</Window>
"@
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load( $reader )
$A.Window = $Window
$NamedElements = @( #"StackHorz",
#"StackLinks",
#"StackRechts",
"LoginButton",
"LoginButtonText",
#"Expander",
"UserTextBox",
"PasswordBox",
"LoginExec",
"ListBoxVM",
# "Grid",
"ButtonVMRefresh",
"TextBoxConsole",
"VMChoiceText",
"StatusText",
"ButtonVMStart",
"ButtonVMStop"
)
try{
$NamedElements | ForEach-Object {$A.Add("$_" , $($Window.FindName("$_")))}
}catch{}
########## Here is the DataContext set for the XAML
$A.Window.DataContext = $A.DataContext
[void]$a.Window.ShowDialog()
}
# Here I create my DataContext and give it some content
$A.VMs = 1..5
$A.MyName = $env:USERNAME
$DataContext = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
$A.DataContext = $DataContext
$DataContext.Add($A.VMs)
$DataContext.Add($A.VM)
$DataContext.Add($A.some)
$DataContext.Add($A.other)
$DataContext.Add($A.stuff)
$DataContext.Add($A.MyName)
# Thread magic is happening here
#region Thread Control
$initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
$newRunspace =[runspacefactory]::CreateRunspace($initialSessionState)
$newRunspace.ApartmentState = "STA"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("A",$A)
$newRunspace.SessionStateProxy.SetVariable("DataContext",$($A.DataContext))
$Gui = [powershell]::Create()
[void]$Gui.addscript($global:GUILayerScript)
$Gui.Runspace = $newRunspace
$GuiThread = $Gui.beginInvoke()
#endregion
答案 0 :(得分:0)
目前,我使用一种变通方法,其中在codebehinde中创建一个事件处理程序,以将用户在GUI中所做的更改写回到哈希表中:
$A.VMChoiceText.add_TextChanged({$A.DataContext[1] = $A.VMChoiceText.Text})
但是我仍然愿意寻求更好的解决方案。