title: How to send GUI informations back to the datacontext
body: <p>First info I don't use C# (yet)! </p>
  
  <hr>
  
  <p>I recently started programming GUI in PowerShell and switched from WinForm to WPF two weeks ago. Now I have a question that is way to simple, so that no tutorial even bothers to announce it.</p>
  
  <p><strong>How do I get the information of the actions I made in the GUI back to work with them??</strong>
  There are plenty of tutorials how to bind my data so that it's shown in my GUI. But now I want to use it the other way around:</p>
  
  <ul>
  <li>I have a Listbox that is bound to an index of my datacontext.</li>
  <li>A Textbox.Text is bound to the selected item of said Listbox.</li>
  <li>Now I want to get that item back to my datacontext.</li>
  </ul>
  
  <p>So far, my datacontext is defined as:</p>
  
  <p><code>$DataContext = New-Object System.Collections.ObjectModel.ObservableCollection[Object]</code></p>
  
  <p>And got some variables added </p>
  
  <pre><code>$DataContext.Add($A.VMs)
  $DataContext.Add($A.VM)
  .
  .
  .
  </code></pre>
  
  <p>What makes it worse is that I try to use it in an extra thread that is supposed to handle just my GUI using this tutorial: <a href="https://learn-powershell.net/2012/10/14/powershell-and-wpf-writing-data-to-a-ui-from-a-different-runspace/" rel="nofollow noreferrer">https://learn-powershell.net/2012/10/14/powershell-and-wpf-writing-data-to-a-ui-from-a-different-runspace/</a></p>
  
  <p>Adding a second binding to the Textbox didn't quite work. Not even a Multibinding: </p>
  
  <pre><code>&lt;TextBox.Text&gt;
    &lt;MultiBinding StringFormat="{}{0}"&gt;
       &lt;Binding Path="SelectedItem"  ElementName ="ListBoxVM" Mode="OneWay" /&gt;
       &lt;Binding Path="[1]" Mode="OneWayToSource" /&gt;
     &lt;/MultiBinding&gt;  
  &lt;/TextBox.Text&gt;
  </code></pre>
  
  <p>My next idea would be to add a binding to the datacontext[1] in code behind to bind it to the TextBox.Text. However, in this setup datacontext has no property I could bind.</p>
  
  <hr>
  
  <p>Edit: I was asked for more Code so here it comes:</p>
  
  <pre><code>    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 = @"
  &lt;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" &gt;
      &lt;StackPanel x:Name = "StackHorz"  Margin = "5" Orientation = "Horizontal"  &gt;
            &lt;StackPanel x:Name = "StackLinks" Margin = "0,0,5,0" &gt;
              &lt;Button x:Name = "LoginButton" ToolTip = "Benutzer wechseln"&gt;
                  &lt;WrapPanel&gt;
                      &lt;TextBlock Text = "Logged in as: " /&gt;
                      &lt;TextBlock x:Name ="LoginButtonText" Text = "{Binding Path=[5]}"/&gt;
                  &lt;/WrapPanel&gt;    
              &lt;/Button&gt;
  
              &lt;ListBox x:Name = "ListBoxVM" ItemsSource = "{Binding Path=[0]}" ToolTip = "VM auswählen" MinHeight = "150" MinWidth = "100" Margin = "0,5,0,5" /&gt;
              &lt;Button x:Name = "ButtonVMRefresh" Content ="Aktualisieren" ToolTip = "Aktualisiert die Anzeige aller VMs" /&gt;
            &lt;/StackPanel&gt;
            &lt;StackPanel x:Name = "StackRechts" &gt;
  
              &lt;Grid x:Name = "Grid" MinHeight = "220" MinWidth = "150" Background="azure"  Margin = "0,0,0,5" &gt;
                  &lt;Grid.ColumnDefinitions&gt;
                      &lt;ColumnDefinition Width = "*"/&gt;
  
                  &lt;/Grid.ColumnDefinitions&gt;
                  &lt;Grid.RowDefinitions&gt;
                      &lt;RowDefinition Height = "Auto"/&gt;
                      &lt;RowDefinition Height = "Auto"/&gt;
                      &lt;RowDefinition Height = "Auto"/&gt;
                      &lt;RowDefinition Height = "Auto"/&gt;
                      &lt;RowDefinition Height = "Auto"/&gt;
                      &lt;RowDefinition Height = "Auto"/&gt;
                  &lt;/Grid.RowDefinitions&gt;
                  &lt;Label Content = "Chosen VM:"  Grid.Column = "0" Grid.Row = "0" HorizontalAlignment="Center" VerticalAlignment="Center" /&gt;
                  &lt;TextBox x:Name = "VMChoiceText"  Grid.Column = "0" Grid.Row = "1" Height = "Auto" ToolTip = "Die aktuell Ausgewählte VM" IsReadOnly = "True" Margin = "10"&gt;
                     &lt;TextBox.Text&gt;
                       &lt;MultiBinding StringFormat="{}{0}"&gt;
                          &lt;Binding Path="SelectedItem"  ElementName ="ListBoxVM" Mode="OneWay" /&gt;
                          &lt;Binding Path="[1]" Mode="OneWayToSource" /&gt;
                       &lt;/MultiBinding&gt;  
                     &lt;/TextBox.Text&gt;
                  &lt;/TextBox&gt; 
                  &lt;Label Content = "Status:" Grid.Column = "0" Grid.Row = "2" HorizontalAlignment="Center" VerticalAlignment="Center" /&gt;
                  &lt;TextBox x:Name = "StatusText" Grid.Column = "0" Grid.Row = "3"  Height = "Auto" ToolTip = "Status der VM" IsReadOnly = "True" Margin = "10,5,10,15"/&gt;
                  &lt;Button x:Name ="ButtonVMStart" Content = "VM start" Grid.Column = "0" Grid.Row = "4" ToolTip ="Startet die ausgewähle VM"  Margin = "10"/&gt;
                  &lt;Button x:Name ="ButtonVMStop" Content = "VM stop" Grid.Column = "0" Grid.Row = "5" ToolTip ="Fährt die ausgewähle VM herunter"  Margin = "10"/&gt;
  
              &lt;/Grid&gt;
              &lt;TextBlock x:Name="TextBoxConsole" Height = "75" Background = "darkblue" Foreground = "white" /&gt;
            &lt;/StackPanel&gt;
       &lt;/StackPanel&gt;
  &lt;/Window&gt;
  
  "@
  
  $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
  </code></pre>