简体   繁体   English

Powershell WPF xaml Treeview绑定理解

[英]powershell wpf xaml treeview binding understanding

I have a script with a gui based on native WPF and XAML (from here: https://foxdeploy.com/functions/ise-snippets/xaml-to-gui/ ). 我有一个基于本地WPF和XAML的gui脚本(来自此处: https//foxdeploy.com/functions/ise-snippets/xaml-to-gui/ )。 The hierarchical structure XAMl Code is from this tutorial: https://dlaa.me/blog/post/9898803 . XAMl代码的分层结构来自于本教程: https ://dlaa.me/blog/post/9898803。 For now I try to figure out how should a pscustomobject should look like to pass it to "Binding SubItems". 现在,我尝试找出pscustomobject应该如何将其传递给“ Binding SubItems”。 How can I declare what is a parent item and whats a childitem? 如何声明什么是父项,什么是子项? I think its very easy but I can not get it. 我认为它很容易,但我无法理解。 I have read and tried a lot but can't find any native WPF examples. 我已经阅读并尝试了很多,但是找不到任何本地WPF示例。 Could anyone point me into the right direction. 谁能指出我正确的方向。 I appreciate any help. 感谢您的帮助。

$inputXML = @"
<Window x:Class="SimpleTreeGridUX.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="SimpleTreeGridUX" Height="400" Width="400">
    <Grid Margin="10">

        <!-- TreeGrid "Control" -->
        <Border BorderBrush="Black" BorderThickness="1">

            <!-- Resources -->
            <Border.Resources>
                <Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
                    <Setter Property="Margin" Value="3 0 3 0"/>
                </Style>
                <Style x:Key="TextBlockBoldStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextBlockStyle}">
                    <Setter Property="FontWeight" Value="Bold"/>
                </Style>
            </Border.Resources>

            <!-- Content -->
            <Grid Grid.IsSharedSizeScope="True">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <!-- Column headers -->
                <TreeViewItem Grid.Row="0" BorderThickness="1">
                    <TreeViewItem.Header>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="Task"/>
                                <!-- Placeholders for two columns of ToggleButton -->
                                <ColumnDefinition SharedSizeGroup="Toggle"/>
                                <ColumnDefinition SharedSizeGroup="Toggle"/>
                                <ColumnDefinition SharedSizeGroup="Duration"/>
                                <ColumnDefinition SharedSizeGroup="Notes"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="Task" Style="{StaticResource TextBlockBoldStyle}"/>
                            <!-- Empty TreeViewItem to measure the size of its ToggleButton into the "Toggle" group-->
                            <TreeViewItem Grid.Column="1" Padding="0"/>
                            <TextBlock Grid.Column="3" Text="Duration" Style="{StaticResource TextBlockBoldStyle}"/>
                            <TextBlock Grid.Column="4" Text="Notes" Style="{StaticResource TextBlockBoldStyle}"/>
                        </Grid>
                    </TreeViewItem.Header>
                </TreeViewItem>

                <!-- Data rows -->
                <TreeView Grid.Row="1" x:Name="treeview" ItemsSource="{Binding SubItems}" BorderBrush="Gray" BorderThickness="0 1 0 0">
                    <TreeView.ItemTemplate>

                        <!-- Level 0 template leaves space for 2 child "Toggle" levels -->
                        <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition SharedSizeGroup="Task"/>
                                    <ColumnDefinition SharedSizeGroup="Toggle"/>
                                    <ColumnDefinition SharedSizeGroup="Toggle"/>
                                    <ColumnDefinition SharedSizeGroup="Duration"/>
                                    <ColumnDefinition SharedSizeGroup="Notes"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0" Text="{Binding Task}" Style="{StaticResource TextBlockStyle}"/>
                                <TextBlock Grid.Column="3" Text="{Binding Duration}" Style="{StaticResource TextBlockStyle}"/>
                                <TextBlock Grid.Column="4" Text="{Binding Notes}" Style="{StaticResource TextBlockStyle}"/>
                            </Grid>

                            <!-- Level 1 template leaves space for 1 child "Toggle" level -->
                            <HierarchicalDataTemplate.ItemTemplate>
                                <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition SharedSizeGroup="Task"/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition SharedSizeGroup="Toggle"/>
                                            <ColumnDefinition SharedSizeGroup="Duration"/>
                                            <ColumnDefinition SharedSizeGroup="Notes"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Grid.Column="0" Text="{Binding Task}" Style="{StaticResource TextBlockStyle}"/>
                                        <TextBlock Grid.Column="3" Text="{Binding Duration}" Style="{StaticResource TextBlockStyle}"/>
                                        <TextBlock Grid.Column="4" Text="{Binding Notes}" Style="{StaticResource TextBlockStyle}"/>
                                    </Grid>

                                    <!-- Level 2 template has no children -->
                                    <HierarchicalDataTemplate.ItemTemplate>
                                        <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
                                            <Grid>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition SharedSizeGroup="Task"/>
                                                    <ColumnDefinition/>
                                                    <ColumnDefinition/>
                                                    <ColumnDefinition SharedSizeGroup="Duration"/>
                                                    <ColumnDefinition SharedSizeGroup="Notes"/>
                                                </Grid.ColumnDefinitions>
                                                <TextBlock Grid.Column="0" Text="{Binding Task}" Style="{StaticResource TextBlockStyle}"/>
                                                <TextBlock Grid.Column="3" Text="{Binding Duration}" Style="{StaticResource TextBlockStyle}"/>
                                                <TextBlock Grid.Column="4" Text="{Binding Notes}" Style="{StaticResource TextBlockStyle}"/>
                                            </Grid>
                                        </HierarchicalDataTemplate>
                                    </HierarchicalDataTemplate.ItemTemplate>
                                </HierarchicalDataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>
                </TreeView>
            </Grid>
        </Border>

    </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 [System.Management.Automation.MethodInvocationException] {
    Write-Warning "We ran into a problem with the XAML code.  Check the syntax for this control..."
    write-host $error[0].Exception.Message -ForegroundColor Red
    if ($error[0].Exception.Message -like "*button*"){
        write-warning "Ensure your &lt;button in the `$inputXML does NOT have a Click=ButtonClick property.  PS can't handle this`n`n`n`n"}
}
catch{#if it broke some other way <img draggable="false" class="emoji" alt="😀" src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/1f600.svg">
    Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."
        }

#===========================================================================
# Store Form Objects In PowerShell
#===========================================================================

$xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name)}

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

#===========================================================================
# Use this space to add code to the various form elements in your GUI
#===========================================================================



$Data = @{     
            Task      = "Main-Task"; 
            Duration  = "10"; 
            Notes     = "notes"; 
            SubItems = @{
                Task      = "Task Ebene 2"; 
                Duration  = "20"; 
                Notes     = "notes2"; 
                SubItems = @{
                    Task      = "Task Ebene 3"; 
                    Duration  = "30"; 
                    Notes     = "notes3"; 
                    }
                }
           }
$Object = New-Object -TypeName PSObject -Property $Data

$WPFtreeview.items.Add($Object)





#Reference 

#Adding items to a dropdown/combo box
    #$vmpicklistView.items.Add([pscustomobject]@{'VMName'=($_).Name;Status=$_.Status;Other="Yes"})

#Setting the text of a text box to the current PC name    
    #$WPFtextBox.Text = $env:COMPUTERNAME

#Adding code to a button, so that when clicked, it pings a system
# $WPFbutton.Add_Click({ Test-connection -count 1 -ComputerName $WPFtextBox.Text
# })
#===========================================================================
# Shows the form
#===========================================================================
write-host "To show the form, run the following" -ForegroundColor Cyan
$Form.ShowDialog() | out-null

@snicz: Thank you very much for your answer, I don't know why your answer is disappeared, guess a technical problem from stackoverflow. @snicz:非常感谢您的回答,我不知道为什么您的答案消失了,请从stackoverflow猜测一个技术问题。 regarding your answer, you posted the code from David Anson's Project: 关于您的答案,您发布了David Anson项目的代码:

        TreeViewItem ParentItem = new TreeViewItem();
        ParentItem.Header = "Parent";
        TreeView1.Items.Add(ParentItem);
        //
        TreeViewItem Child1Item = new TreeViewItem();
        Child1Item.Header = "Child One";
        ParentItem.Items.Add(Child1Item);
        //
        TreeViewItem Child2Item = new TreeViewItem();
        Child2Item.Header = "Child Two";
        ParentItem.Items.Add(Child2Item);
        TreeViewItem SubChild1Item = new TreeViewItem();
        SubChild1Item.Header = "Sub Child One";
        Child2Item.Items.Add(SubChild1Item);
        TreeViewItem SubChild2Item = new TreeViewItem();
        SubChild2Item.Header = "Sub Child Two";
        Child2Item.Items.Add(SubChild2Item);
        TreeViewItem SubChild3Item = new TreeViewItem();
        SubChild3Item.Header = "Sub Child Three";
        Child2Item.Items.Add(SubChild3Item);
        //
        TreeViewItem Child3Item = new TreeViewItem();
        Child3Item.Header = "Child Three";
        ParentItem.Items.Add(Child3Item);
        //
        ParentItem.IsExpanded = true;
        Child2Item.IsExpanded = true;
    }

I also found this but I'm looking for a "powershell only" way, how would exactly this looks like if I create pscustomobject? 我也发现了这一点,但是我正在寻找一种“仅Powershell”方式,如果我创建pscustomobject的话,它将是什么样子? I also found some Windows Forms Examples but I would like to include it in a project thats only XAML and WPF/Powershell (like the Code in initial Question above). 我还找到了一些Windows窗体示例,但我想将其包含在仅XAML和WPF / Powershell的项目中(例如上述初始问题中的代码)。

I'm not sure if its clear what I'am talking about? 我不确定我在说什么吗?

got it working this way: Sure, there is a much shorter way, but it may help someone to understand it easier. 可以这样工作:当然,有一种更短的方法,但是它可以帮助人们更容易地理解它。

$inputXML = @"
<Window x:Class="SimpleTreeGridUX.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="SimpleTreeGridUX" Height="400" Width="400">
    <Grid Margin="10">

        <!-- TreeGrid "Control" -->
        <Border BorderBrush="Black" BorderThickness="1">

            <!-- Resources -->
            <Border.Resources>
                <Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
                    <Setter Property="Margin" Value="3 0 3 0"/>
                </Style>
                <Style x:Key="TextBlockBoldStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextBlockStyle}">
                    <Setter Property="FontWeight" Value="Bold"/>
                </Style>
            </Border.Resources>

            <!-- Content -->
            <Grid Grid.IsSharedSizeScope="True">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <!-- Column headers -->
                <TreeViewItem Grid.Row="0" BorderThickness="1">
                    <TreeViewItem.Header>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="Task"/>
                                <!-- Placeholders for two columns of ToggleButton -->
                                <ColumnDefinition SharedSizeGroup="Toggle"/>
                                <ColumnDefinition SharedSizeGroup="Toggle"/>
                                <ColumnDefinition SharedSizeGroup="Duration"/>
                                <ColumnDefinition SharedSizeGroup="Notes"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="Task" Style="{StaticResource TextBlockBoldStyle}"/>
                            <!-- Empty TreeViewItem to measure the size of its ToggleButton into the "Toggle" group-->
                            <TreeViewItem Grid.Column="1" Padding="0"/>
                            <TextBlock Grid.Column="3" Text="Duration" Style="{StaticResource TextBlockBoldStyle}"/>
                            <TextBlock Grid.Column="4" Text="Notes" Style="{StaticResource TextBlockBoldStyle}"/>
                        </Grid>
                    </TreeViewItem.Header>
                </TreeViewItem>

                <!-- Data rows -->
                <TreeView Grid.Row="1" x:Name="treeview" ItemsSource="{Binding SubItems}" BorderBrush="Gray" BorderThickness="0 1 0 0">
                    <TreeView.ItemTemplate>

                        <!-- Level 0 template leaves space for 2 child "Toggle" levels -->
                        <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition SharedSizeGroup="Task"/>
                                    <ColumnDefinition SharedSizeGroup="Toggle"/>
                                    <ColumnDefinition SharedSizeGroup="Toggle"/>
                                    <ColumnDefinition SharedSizeGroup="Duration"/>
                                    <ColumnDefinition SharedSizeGroup="Notes"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0" Text="{Binding Task}" Style="{StaticResource TextBlockStyle}"/>
                                <TextBlock Grid.Column="3" Text="{Binding Duration}" Style="{StaticResource TextBlockStyle}"/>
                                <TextBlock Grid.Column="4" Text="{Binding Notes}" Style="{StaticResource TextBlockStyle}"/>
                            </Grid>

                            <!-- Level 1 template leaves space for 1 child "Toggle" level -->
                            <HierarchicalDataTemplate.ItemTemplate>
                                <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition SharedSizeGroup="Task"/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition SharedSizeGroup="Toggle"/>
                                            <ColumnDefinition SharedSizeGroup="Duration"/>
                                            <ColumnDefinition SharedSizeGroup="Notes"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Grid.Column="0" Text="{Binding Task}" Style="{StaticResource TextBlockStyle}"/>
                                        <TextBlock Grid.Column="3" Text="{Binding Duration}" Style="{StaticResource TextBlockStyle}"/>
                                        <TextBlock Grid.Column="4" Text="{Binding Notes}" Style="{StaticResource TextBlockStyle}"/>
                                    </Grid>

                                    <!-- Level 2 template has no children -->
                                    <HierarchicalDataTemplate.ItemTemplate>
                                        <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
                                            <Grid>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition SharedSizeGroup="Task"/>
                                                    <ColumnDefinition/>
                                                    <ColumnDefinition/>
                                                    <ColumnDefinition SharedSizeGroup="Duration"/>
                                                    <ColumnDefinition SharedSizeGroup="Notes"/>
                                                </Grid.ColumnDefinitions>
                                                <TextBlock Grid.Column="0" Text="{Binding Task}" Style="{StaticResource TextBlockStyle}"/>
                                                <TextBlock Grid.Column="3" Text="{Binding Duration}" Style="{StaticResource TextBlockStyle}"/>
                                                <TextBlock Grid.Column="4" Text="{Binding Notes}" Style="{StaticResource TextBlockStyle}"/>
                                            </Grid>
                                        </HierarchicalDataTemplate>
                                    </HierarchicalDataTemplate.ItemTemplate>
                                </HierarchicalDataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>
                </TreeView>
            </Grid>
        </Border>

    </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 [System.Management.Automation.MethodInvocationException] {
    Write-Warning "We ran into a problem with the XAML code.  Check the syntax for this control..."
    write-host $error[0].Exception.Message -ForegroundColor Red
    if ($error[0].Exception.Message -like "*button*"){
        write-warning "Ensure your &lt;button in the `$inputXML does NOT have a Click=ButtonClick property.  PS can't handle this`n`n`n`n"}
}
catch{#if it broke some other way <img draggable="false" class="emoji" alt="😀" src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/1f600.svg">
    Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."
        }

#===========================================================================
# Store Form Objects In PowerShell
#===========================================================================

$xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name)}

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

#===========================================================================
# Use this space to add code to the various form elements in your GUI
#===========================================================================


$Data=[pscustomobject]@{Task='Erster Haupteintrag';Duration="10";Notes="notes 1"}

$Child=[pscustomobject]@{Task="Zweite Ebene";Duration="20"; Notes="notes 22"}
$Data2=[pscustomobject]@{Task='Zweiter Haupteintrag';Duration="20";Notes="notes 2"; Subitems=@($Child)}

$Child3=[pscustomobject]@{Task="Dritte Ebene";Duration="35"; Notes="notes 3"}
$Child2=[pscustomobject]@{Task="Zweite Ebene 2";Duration="20"; Notes="notes 222"; Subitems=@($Child3)}
$Data3=[pscustomobject]@{Task='Dritter Haupteintrag';Duration="30";Notes="notes 3"; Subitems=@($Child2)}

$WPFtreeview.items.Add($Data)
$WPFtreeview.items.Add($Data2)
$WPFtreeview.items.Add($Data3)



#Reference 

#Adding items to a dropdown/combo box
    #$vmpicklistView.items.Add([pscustomobject]@{'VMName'=($_).Name;Status=$_.Status;Other="Yes"})

#Setting the text of a text box to the current PC name    
    #$WPFtextBox.Text = $env:COMPUTERNAME

#Adding code to a button, so that when clicked, it pings a system
# $WPFbutton.Add_Click({ Test-connection -count 1 -ComputerName $WPFtextBox.Text
# })
#===========================================================================
# Shows the form
#===========================================================================
write-host "To show the form, run the following" -ForegroundColor Cyan
$Form.ShowDialog() | out-null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM