Search code examples
wpfpowershelldata-bindinglistviewitemitemssource

ListItems only show after window is resized


I create a window from PowerShell that contains a ListView. The ListView gets its items from ItemsSource with binding. The list gets filled without problem, but when all is done, the listviewitems are not shown. They are only shown when I resize the window.

Same goes if I run again, any new items are only shown after I resize the window.

XAML:

<ListView Grid.Column="0" Name="Lv1">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="N" DisplayMemberBinding="{Binding Name}" Width="200"/>
            <GridViewColumn Header="I" DisplayMemberBinding="{Binding LastWriteTime}" Width="150"/>
        </GridView>
    </ListView.View>
</ListView>

PowerShell, I have tried with PSCustomObject, PSObject, hashtable, but same result:

$Something = { param( $syncHash )
# Gather stuff in $t
$syncHash.DataContext[4].Add( [pscustomobject]@{ Name = $t.Name; LastWriteTime = $t.LastWriteTime } )
}

$syncHash = [hashtable]::Synchronized(@{})
$syncHash.Window = [Windows.Markup.XamlReader]::Load( ( New-Object System.Xml.XmlNodeReader ( [xml]( Get-Content .\tt.xml ) ) ) )
$syncHash = [hashtable]::Synchronized(@{})
$Bindings = New-Object System.Collections.ArrayList
$Lv1Source = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
$Lv2Source = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
0.0, 0.0, "", 0.0, $Lv1Source, $Lv2Source | foreach { $syncHash.DataContext.Add( $_ ) }
$syncHash.Button.Add_Click( {
    ( [powershell]::Create().AddScript( $Something ).AddArgument( $syncHash ) ).BeginInvoke()
} )
$syncHash.Window.DataContext = $syncHash.DataContext
0..( $syncHash.DataContext.Count - 1 ) | foreach { [void]$Bindings.Add( ( New-Object System.Windows.Data.Binding -ArgumentList "[$_]" ) ) }
$Bindings | foreach { $_.Mode = [System.Windows.Data.BindingMode]::OneWay }

[void][System.Windows.Data.BindingOperations]::SetBinding( $syncHash.Lv1, [System.Windows.Controls.ListView]::ItemsSourceProperty, $Bindings[4] )
[void][System.Windows.Data.BindingOperations]::SetBinding( $syncHash.Lv2, [System.Windows.Controls.ListView]::ItemsSourceProperty, $Bindings[5] )

$syncHash.DataContext[4].Add( [pscustomobject]@{Name=$t.Name;LastWriteTime=$t.LastWriteTime } )

Solution

  • I found a solution to the problem thanks to the last post here, "When calling between runspaces we need to use the 'Dispatcher'".

    In conclusion, the DataContext is updated through the syncHash, but in the scriptblock for the button-click, I need to use:

    $syncHash.Window.Dispatcher.Invoke( [action] {
    $syncHash.Lv1.Items.Refresh()
    $syncHash.DataContext[5].Add( [pscustomobject]@{ Name = $syncHash.h[$syncHash.ti] ; LastWriteTime = ( Get-Date ) } )
    } )