Powershell ListView using WPF - Items not showing properly - wpf

Im trying to output into two columns the result of the following query:
get-mailbox -identity *#$SearchDomain | where ismailboxenabled -eq true
Here is what i've done right now:
$mailboxes = get-mailbox -identity *#$SearchDomain | where ismailboxenabled -eq true
foreach($line in $mailboxes){
$new = new-object System.Windows.Forms.ListViewItem($line.Name)
$new.SubItems.Add($line.Alias + "#" + $SearchDomain)
$WPFLstActiveMailboxes.Items.Add($new)
}
My problem is that things are showing up like this in my GUI:
Behind the black boxes is the data that I want
EDIT 1:
$inputXML = #"
<Window x:Name="TMS_MailboxToolkit" x:Class="TMS_MailboxToolki.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TMS"
mc:Ignorable="d"
Title="TMS - Mailbox Toolkit" Height="354.303" Width="527.152">
<Grid Margin="0,0,-8,-5">
<Button x:Name="BtnCalculate" Content="Calculate" HorizontalAlignment="Left" Margin="432,289,0,0" VerticalAlignment="Top" Width="75"/>
<Label x:Name="LblSearchDomain" Content="Search domain" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<TextBox x:Name="TxtSearchDomain" HorizontalAlignment="Left" Height="23" Margin="10,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="malicis.com"/>
<Label x:Name="LblActiveMailboxes" Content="Active mailboxes" HorizontalAlignment="Left" Margin="10,74,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<Label x:Name="LblCurrentCount" Content="Current count:" HorizontalAlignment="Left" Margin="10,286,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="TxtCurrentCount" HorizontalAlignment="Left" Height="23" Margin="101,290,0,0" TextWrapping="Wrap" Text="00000" VerticalAlignment="Top" Width="45" IsEnabled="False" FontWeight="Bold"/>
<ProgressBar x:Name="PrgStatus" HorizontalAlignment="Left" Height="10" Margin="345,70,0,0" VerticalAlignment="Top" Width="162"/>
<TextBox x:Name="TxtStatus" HorizontalAlignment="Left" Height="23" Margin="345,42,0,0" TextWrapping="Wrap" IsEnabled="False" Text="idle" VerticalAlignment="Top" Width="162" FontStyle="Italic"/>
<Label x:Name="LblStatus" Content="Status" HorizontalAlignment="Left" Margin="345,10,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<ListView x:Name="LstActiveMailboxes" HorizontalAlignment="Left" Height="181" Margin="10,100,0,0" VerticalAlignment="Top" Width="497">
<ListView.View>
<GridView>
<GridViewColumn Header="Disable">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Margin="5, 0" IsChecked="False"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn >
<GridViewColumn Header="Name"/>
<GridViewColumn Header="Alias"/>
<GridViewColumn Header="Mailbox"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
"#
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged properties (PowerShell cannot process them)"
throw}
#===========================================================================
# Load XAML Objects In PowerShell
#===========================================================================
$xaml.SelectNodes("//*[#Name]") | %{"trying item $($_.Name)";
try {Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop}
catch{throw}
}
Function Get-FormVariables{
if ($global:ReadmeDisplay -ne $true){Write-host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow;$global:ReadmeDisplay=$true}
write-host "Found the following interactable elements from our form" -ForegroundColor Cyan
get-variable WPF*
}
Get-FormVariables
#===========================================================================
# Shows the form
#===========================================================================
Add-Type -AssemblyName System.Windows.Forms
Set-Variable -Name credsalreadyprovided -Value $false -Scope global
Set-Variable -Name CONFIG_SERVER -Value "exchpd01" -Scope global
$WPFBtnCalculate.Add_Click({
if ($credsalreadyprovided -eq $true){
calculate
}
else{
initiatesession
calculate
}
})
function initiatesession{
$WPFPrgStatus.Value = 0
Set-Variable -Name cred -Value (get-credential) -Scope global
$credsalreadyprovided = $true
$WPFPrgStatus.Value = 25
$WPFTxtStatus.Text = "Establishing session with " + $CONFIG_SERVER + "..."
Set-Variable -Name session -Value (New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$CONFIG_SERVER/PowerShell/ -credential $cred) -Scope global
$WPFPrgStatus.Value = 50
$WPFTxtStatus.Text = "Importing session..."
Import-PSSession $session -AllowClobber
}
function calculate{
$WPFPrgStatus.Value = 100
$WPFTxtStatus.Text = "Querying " + $CONFIG_SERVER + "..."
$SearchDomain=$WPFTxtSearchDomain.Text
$WPFTxtCurrentCount.Text = (get-Mailbox -identity *#$SearchDomain | where ismailboxenabled -eq true).count
#$mailboxes = get-mailbox -identity *#$SearchDomain | where ismailboxenabled -eq true
get-mailbox -identity *#$SearchDomain | where ismailboxenabled -eq true | ForEach-Object{
$name = $_.Name
$entry = New-Object System.Windows.Controls.ListViewItem($name)
$alias = $_.Alias
$entry.SubItems.Add($alias)
$mailbox = $_.Alias + "#" + $SearchDomain
$entry.SubItems.Add($mailbox)
$WPFLstActiveMailboxes.Items.Add($entry)
}
}
$Form.ShowDialog() | out-null

What I have always done is use databinding in WPF so that it is bound to the property that I want and then just create a psobject with those properties that I have bindings for in WPF, and then just add them to the ListView.Items collection.
Here is a reference of the wpf setup, and then just make sure to have your psobject properties the exact same as the binding properties in the wpf
DataGridView Column binding in WPF

Related

PowerShell and XAML data binding

I'm trying to get a list of users searching by a surname property and list them in the ListView.
Here's XAML code:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Find users with SamAccountName"
Width="525"
Background="#FF262626"
ResizeMode="NoResize"
SizeToContent="Height">
<StackPanel Margin="5,5,5,5" Orientation="Vertical">
<Grid
Name="Grid"
Width="400"
Height="200"
Background="#313130">
<Label
Name="Label"
Content="Select employee"
FontSize="12"
Foreground="White" />
<ListView
Name="ListView"
Margin="0,25,0,0"
Background="Transparent"
BorderBrush="Transparent"
Foreground="White"
IsHitTestVisible="False"
SelectionMode="Single">
<ListView.View>
<GridView>
<GridViewColumn
Width="100"
DisplayMemberBinding="{Binding Path=Logon}"
Header="Logon" />
<GridViewColumn
Width="150"
DisplayMemberBinding="{Binding Path=FirstName}"
Header="First name" />
<GridViewColumn
Width="150"
DisplayMemberBinding="{Binding Path=LastName}"
Header="Last name" />
</GridView>
</ListView.View>
</ListView>
</Grid>
<StackPanel HorizontalAlignment="Right">
<Button Width="50" Content="SAVE" />
</StackPanel>
</StackPanel>
And it looks like this:
XAML look
I believe I cannot do it without data-binding and I saw a lot of posts about them but I couldn't understand it completely.
For now in powershell I have:
Add-Type -AssemblyName PresentationFramework
$employees = Get-ADUser -Filter {Surname -like "surname"}
$itemSource = #()
ForEach ($employee in ($employees | Sort-Object SamAccountName)) {
$itemSource += [PSCustomObject]# {
Logon = $employee.Name
FirstName = $employee.GivenName
LastName = $employee.Surname
}
$columnOrder = 'Logon', 'FirstName', 'LastName'
[XML]$Form = Get-Content "xmlPath"
$NR = (New-Object System.Xml.XmlNodeReader $Form)
$Win = [Windows.Markup.XamlReader]::Load($NR)
$Win.ShowDialog()
Now, the ForEach is working perfectly fine and returning exactly what I need but cannot find any way to put it into ViewList.
Then I'll need to save the selected user into a variable that I'll display later in the textbox.
Sorry if it's a stupid/easy question but I just started learning PowerShell to help me automate my work.
In the loaded form, you have to specify the ListView's ItemsSource
in PowerShell, you can do it like this
Add-Type -AssemblyName PresentationFramework
$employees = Get-ADUser -Filter {Surname -like "surname"}
$itemSource = #()
ForEach ($employee in $($employees | Sort-Object SamAccountName)) {
$itemSource += [PSCustomObject]#{
Logon = $employee.Name
FirstName = $employee.GivenName
LastName = $employee.Surname
}
}
[XML]$Form = (Get-Content "C:\temp\test.xaml")
$NR = (New-Object System.Xml.XmlNodeReader $Form)
$Win = [Windows.Markup.XamlReader]::Load($NR)
# this part
($win.FindName("ListView")).ItemsSource = $itemSource
$Win.ShowDialog()

Powershell WPF update on Event

I'm having trouble updating my WPF-Window-Forms.
Basically, I want to trigger different content in my "Console-TextBox" depending on the current connected Network-SSID.
[xml]$xaml = Get-Content -Path $PSScriptRoot\Pattern.xaml
$manager = New-Object System.Xml.XmlNamespaceManager -ArgumentList $xaml.NameTable
$manager.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml");
$xamlReader = New-Object System.Xml.XmlNodeReader $xaml
[Windows.Markup.XamlReader]::Load($xamlReader)
}
$window = Load-Xaml
$textbox = $window.FindName("textbox")
$textbox_console = $window.FindName("textbox_console")
Get-EventSubscriber | Unregister-Event
Register-EngineEvent -SourceIdentifier 'MyEvent' -Action {$textbox_console.Text += "ManualInput"}
$networkChange = [System.Net.NetworkInformation.NetworkChange];
Register-ObjectEvent -InputObject $networkChange -EventName NetworkAddressChanged -SourceIdentifier NetworkChanged -Action {
$textbox_console.Text += "`nNetworkChanged"
}
$textbox.Add_TextChanged({
New-Event -SourceIdentifier 'MyEvent'
})
$window.ShowDialog() | Out-Null
XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Pattern" Width="600" Height="400" WindowStyle="None" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen">
<StackPanel>
<TextBox x:Name="textbox" HorizontalAlignment="Left" Height="70" Margin="124,104,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="262"/>
<TextBox x:Name="textbox_console" HorizontalAlignment="Left" Height="70" Margin="124,104,0,0" TextWrapping="Wrap" Text="console" VerticalAlignment="Top" Width="262"/>
</StackPanel>
</Window>
I'm new to Event Handling and not sure whether this issue is caused by Thread/Process-handling or wrong EventHandling...
Maybe somebody could point out some hint and tell me, how to use the NetworkChange-Event to update the text of the textbox?

WPF/PowerShell, copy single cell from a datagrid without header

In a WPF DataGrid via PowerShell, I would like the user to be able to copy the cells as follows: 1) if multiple cells and rows are selected selected then copy it with header. 2) If only a single cell is selected copy the cell content without the header. In the sample shown below, I've set ClipboardCopyMode="IncludeHeader" which enables to copy the selected cells/rows with header which satisfies first requirement indicated above. However, I'm looking for some ideas or quick samples for the second requirement shown above, that is to copy the content without header if only single cell is selected (from context menu or shortcut). I had tried mouse events but couldn't get it to work. Thanks in advance.
[xml]$xaml=#"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test"
Title="MainWindow" Height="425" Width="550">
<Grid>
<TextBox x:Name="tb_Search" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="149"/>
<Button x:Name="bt_Search" Content="Search" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" IsDefault="True" Height="22" Margin="165,10,0,0" />
<DataGrid x:Name="dg" Margin="10,45,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="100" Height="Auto" Width="Auto" ColumnWidth="Auto" AlternationCount="1" IsReadOnly="True" SelectionMode="Extended" SelectionUnit="Cell" Background="White" ClipboardCopyMode="IncludeHeader">
<DataGrid.ContextMenu>
<ContextMenu >
<MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy With Header"/>
<MenuItem Command="{x:Static ApplicationCommands.Save}" Header="Save"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</Grid>
</Window>
"#
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load($reader)
#Turn XAML into PowerShell objects
$xaml.SelectNodes("//*[#*[contains(translate(name(.),'n','N'),'x:Name')]]") | ForEach-Object{
Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name)
}
#sample data
$DataSet = New-Object System.Data.DataSet
$Table = $DataSet.Tables.Add("Table")
$Properties = #("Country","Capital","Population")
$Properties | foreach {
$Column = New-Object System.Data.DataColumn($_)
$Table.Columns.Add($Column)
}
$Null=$Table.Rows.Add("China PR","Beijing","20,693,000")
$Null=$Table.Rows.Add("India","New Delhi","16,787,949")
$Null=$Table.Rows.Add("Japan","Tokyo","13,189,000")
$Null=$Table.Rows.Add("Philippines","Manila","12,877,253")
$Null=$Table.Rows.Add("Russia","Moscow","11,541,000")
$Null=$Table.Rows.Add("Egypt","Cairo","10,230,350")
$Null=$Table.Rows.Add("USA","Washington, D.C","658,893")
$Null=$Table.Rows.Add("China PR","Beijing","20,693,000")
$Null=$Table.Rows.Add("India","New Delhi","16,787,949")
$Null=$Table.Rows.Add("Japan","Tokyo","13,189,000")
$Null=$Table.Rows.Add("Philippines","Manila","12,877,253")
$Null=$Table.Rows.Add("Russia","Moscow","11,541,000")
$Null=$Table.Rows.Add("Egypt","Cairo","10,230,350")
$Null=$Table.Rows.Add("USA","Washington, D.C","658,893")
#populate datagrid
$DataView = New-Object System.Data.DataView($Table)
$array = New-Object System.Collections.ArrayList
[void] $array.AddRange($DataView)
$dg.clear()
$dg.ItemsSource = $array
$dg.IsReadOnly = $true
$bt_Search.Add_Click({
$SearchValue = $tb_Search.text
for ($i = 0; $i -lt $dg.Items.Count; $i++)
{
if ($dg.Items[$i].Row[$dg.Columns.DisplayIndex] -eq "$SearchValue")
{
[System.Windows.Forms.MessageBox]::Show("Keyword Found")
$dg.ScrollIntoView($dg.Items[$i]) #scroll to the row that contains the keyword searched
}
}
})
#Display Form
$Window.ShowDialog() | Out-Null
You could dynamically set the ClipboardCopyMode in the CanExcecute method of the ApplicationCommands.Copy command. This is how you would do this in C#:
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
DataGrid dataGrid = (DataGrid)sender;
dataGrid.ClipboardCopyMode = dataGrid.SelectedCells.Count == 1 ?
DataGridClipboardCopyMode.ExcludeHeader : DataGridClipboardCopyMode.IncludeHeader;
}
XAML:
<DataGrid ... SelectionMode="Extended" SelectionUnit="Cell" ClipboardCopyMode="IncludeHeader">
<DataGrid.CommandBindings>
<CommandBinding Command="{x:Static ApplicationCommands.Copy}" CanExecute="CommandBinding_CanExecute"/>
</DataGrid.CommandBindings>
</DataGrid>

PowerShell WPF - Binding DataGrid ComboBox to Column In ItemsSource

I am trying to populate a ComboBox within a DataGrid with unique values from a given column, however I'm getting unexpected results in that it splits the value from that row into individual characters and populates each ComboBox with said characters.
Here's a simple example script of my issue;
$csv = "ID,Fruit,Owner`r`n"
$csv += "1,Apple,Andrew`r`n"
$csv += "2,Banana,Bill`r`n"
$csv += "3,Cherry,Charles`r`n"
$csv += "4,Date,Daniel`r`n"
$csv += "5,Elderberry,Ethan`r`n"
$data = ConvertFrom-Csv $csv
$inputXML = #"
<Window x:Name="DataGridComboTest" x:Class="DataGridComboTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataGridComboTest" Width="640" Height="480" WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid x:Name="DataGrid" Margin="10,10,10,10" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ID}" Header="ID"/>
<DataGridTextColumn Binding="{Binding Fruit}" Header="Fruit"/>
<DataGridTextColumn Binding="{Binding Owner}" Header="Owner"/>
<DataGridTemplateColumn Header="Owner Combo">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
SelectedItem="{Binding Path=Owner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Owner}"
Text="{Binding Path=Owner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
"#
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Form=[Windows.Markup.XamlReader]::Load( $reader )
$xaml.SelectNodes("//*[#Name]") | %{ Set-Variable -Name "$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop }
$DataGrid.ItemsSource = $data
$Form.ShowDialog() | Out-Null
What I'd like to be able to do is select a different owner for each fruit from the existing owners in the table, however instead I'm given a choice of each letter in the adjacent owner's name;
You should bind the ItemsSource to an IEnumerable<string> rather than a scalar string (which is an IEnumerable<char>).
Try something like this:
...
ItemsSource="{DynamicResource owners}"
...
$owners = $data | Select-Object -ExpandProperty Owner -Unique
$Form.Resources.Add("owners", $owners)
With mm8's help I was able to come up with a working script;
$csv = "ID,Fruit,Owner`r`n"
$csv += "1,Apple,Andrew`r`n"
$csv += "2,Banana,Bill`r`n"
$csv += "3,Cherry,Charles`r`n"
$csv += "4,Date,Daniel`r`n"
$csv += "5,Elderberry,Ethan`r`n"
$csv += "6,Fig,Bill`r`n"
$csv += "7,Grape,Daniel`r`n"
$data = ConvertFrom-Csv $csv
$inputXML = #"
<Window x:Name="DataGridComboTest" x:Class="DataGridComboTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataGridComboTest" Width="640" Height="480" WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid x:Name="DataGrid" Margin="10,10,10,10" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ID}" Header="ID"/>
<DataGridTextColumn Binding="{Binding Fruit}" Header="Fruit"/>
<DataGridTextColumn Binding="{Binding Owner}" Header="Owner"/>
<DataGridTemplateColumn Header="Owner Combo">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
SelectedItem="{Binding Path=Owner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{DynamicResource owners}"
Text="{Binding Path=Owner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
"#
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Form=[Windows.Markup.XamlReader]::Load( $reader )
$xaml.SelectNodes("//*[#Name]") | %{ Set-Variable -Name "$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop }
$DataGrid.ItemsSource = $data
#$owners = [Linq.Enumerable]::ToArray($data | Select-Object -ExpandProperty Owner)
$owners = $data | Select-Object -ExpandProperty Owner -Unique
$Form.Resources.Add("owners", $owners)
$Form.ShowDialog() | Out-Null
The DynamicResource binding was key, but the [Linq.Enumerable] line from mm8's answer threw an error. However simplifying it to select unique owners from $data resolved this. I also added a couple of duplicate owners to the source data to more accurately simulate a real-world scenario, hence "-Unique".

DataGrid AddChild in Runspace

I've created a PowerShell Runspace and wanted to populate a DataGrid from a CSV file. The code works fine without a Runspace, but not in it.
I think the error must be in this two lines, but I can't get it:
$csv = Import-Csv "C:\name.csv" -Delimiter ";" -Encoding UTF8 |
Select-Object #{Name='USER';Expression={$_.USER}},`#{Name='ID';Expression={$_.ID}}
$csv | % { $syncHash.dgusers.AddChild($_) }
With this two lines in the code. The GUI won't show up.
The full code:
Add-Type -AssemblyName PresentationFramework
$syncHash = [hashtable]::Synchronized(#{})
$Runspace =[runspacefactory]::CreateRunspace()
$Runspace.ApartmentState = "STA"
$Runspace.ThreadOptions = "ReuseThread"
$Runspace.Open()
$Runspace.SessionStateProxy.SetVariable("syncHash", $syncHash)
$code = {
#Build the GUI
[xml]$xaml = #"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="UserList" Height="368" Width="525" WindowStyle="ToolWindow" Topmost="True" ResizeMode="NoResize">
<Grid>
<TabControl Name="tabControl" HorizontalAlignment="Left" Height="308" Margin="18,10,0,0" VerticalAlignment="Top" Width="481">
<TabItem Header="Lieferanten">
<Grid Background="#ffffff">
<DataGrid Name="dgusers" AutoGenerateColumns="False" Margin="19,27,158,20">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="40" />
<DataGridTextColumn Header="USER" Binding="{Binding USER}" Width="233"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
"#
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$syncHash.Window=[Windows.Markup.XamlReader]::Load($reader)
$syncHash.Error = $Error
# XAML objects
$syncHash.dgusers = $syncHash.window.FindName("dgusers")
$csv = Import-Csv "C:\name.csv" -Delimiter ";" -Encoding UTF8 |
Select-Object #{Name='USER';Expression={$_.USER}},`#{Name='ID';Expression={$_.ID}}
$csv | % { $syncHash.dgusers.AddChild($_) }
$syncHash.Window.ShowDialog()
$Runspace.Close()
$Runspace.Dispose()
}
$PSinstance1 = [powershell]::Create().AddScript($Code)
$PSinstance1.Runspace = $Runspace
$job = $PSinstance1.BeginInvoke()

Resources