Question

I'm having problems figuring out the syntax for itemscontrol databinding in powershell. I have a simple WPF script below with 2 examples of itemscontrol with a data template. The first one (list01) has multiple elements and does not show properly, the 2nd itemscontrol (list02) has only one binding element and works just fine.

I'm looking for the correct syntax to bind objects to the first itemscontrol (list01).

Complete powershell script (:

[xml]$xaml = @'

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="MainWindow"
        Title="ItemsControlDataBindingSample" Height="350" Width="300">
<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition MinHeight="20"/>
        <RowDefinition MinHeight="50"/>
        <RowDefinition MinHeight="50"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50"/>
    </Grid.ColumnDefinitions>

    <ItemsControl Name="LIST01" Grid.Row="1">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid Margin="5">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="100" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Title}" />
                    <ProgressBar Grid.Column="1" Minimum="0" Maximum="100" Value="{Binding Completion}" />
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

    <ItemsControl Name="LIST02" Grid.Row="2">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid Margin="5">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Label Content="{Binding}"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

    </Window>
    '@

#New-Object System.Windows.Controls.ItemsControl

[void][System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework')
[void][reflection.assembly]::LoadWithPartialName('System.Drawing')

#Read XAML
$Form = [Windows.Markup.XamlReader]::Load( (New-Object System.Xml.XmlNodeReader $xaml) )

#Find objects
$MainWindow = $Form.FindName('MainWindow')
$List01 = $Form.FindName('LIST01')
$List02 = $Form.FindName('LIST02')

## this does not work ##
$Source01 = @(
    [ordered]@{ Title=([string]'Complete this WPF tutorial'); Completion=([int]45) },
    [ordered]@{ Title=([string]'Learn C#'); Completion=([int]80) },
    [ordered]@{ Title=([string]'Wash the car'); Completion=([int]25) }
    [ordered]@{ Title=([string]'Make KIDS do homework'); Completion=([int]3) }
);
## this does not work ##
$Source01 = @{ title='test01'; completion=50 }

## this does not work ##
$testArray = @()
$tmpObject = Select-Object -InputObject "" Title,Completion
$tmpObject.Title = 'Complete this WPF tutorial'
$tmpObject.Completion = 45
$testArray += $tmpObject

$List01.ItemsSource = $testArray
#$List01 | gm -type method


## this WORKS ##
$Source02 = @('TEST01','TEST02','TEST03')
$List02.ItemsSource = $Source02

[void]$Form.ShowDialog();

This code is based off a very simple C# example: http://www.wpf-tutorial.com/list-controls/itemscontrol

However, I'm not sure how that syntax directly transates to powershell.

Was it helpful?

Solution

I would probably suggest using an MVVM approach. Just set the DataContext property of the window and then bind the ItemsControl.ItemsSource property to the list you want, e.g. ItemsSource="{Binding MyItemsListProperty}".

A full example of what this could look like (based on the example code you posted above):

$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="MainWindow"
        Title="ItemsControlDataBindingSample" Height="350" Width="300">
<Grid Margin="10">

    <ItemsControl ItemsSource="{Binding MyItemsListProperty}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid Margin="5">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="100" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Title}" />

                    <ProgressBar Grid.Column="1" Minimum="0" Maximum="100" Value="{Binding Completion}" />
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

</Grid>
</Window>
"@

[void][System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework')

#Read XAML
$window = [Windows.Markup.XamlReader]::Parse($xaml)

$viewModel = New-Object PSObject -Property @{
    MyItemsListProperty = @(    
        New-Object PSObject -Property @{ 
            Title='Complete this WPF tutorial'
            Completion=45.0 
        };    
        New-Object PSObject -Property @{ 
            Title='Learn C#'
            Completion=80.0 
        };    
        New-Object PSObject -Property @{ 
            Title='Wash the car'
            Completion=25.0
        };    
        New-Object PSObject -Property @{ 
            Title='Make KIDS do homework'
            Completion=3.0 
        };
    )
};

$window.DataContext = $viewModel

$window.ShowDialog()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top