Created
January 4, 2019 18:47
-
-
Save jrich523/c49531a87b274debcf75c9c3171fc79a to your computer and use it in GitHub Desktop.
powershell show object advanced
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Show-Object{ | |
param( | |
## The object to examine | |
[Parameter(ValueFromPipeline = $true)] | |
$InputObject | |
) | |
#custom controls for treeview... found it on MSDN a while ago, lost link :-/ | |
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | |
add-type @" | |
using System; | |
using System.Windows.Controls; | |
using System.Windows; | |
using System.Windows.Data; | |
using System.Globalization; | |
namespace _treeListView | |
{ | |
public class TreeListView : TreeView | |
{ | |
protected override DependencyObject GetContainerForItemOverride() | |
{ | |
return new TreeListViewItem(); | |
} | |
protected override bool IsItemItsOwnContainerOverride(object item) | |
{ | |
return item is TreeListViewItem; | |
} | |
} | |
public class TreeListViewItem : TreeViewItem | |
{ | |
private int _level = -1; | |
public int Level | |
{ | |
get | |
{ | |
if (_level != -1) return _level; | |
var parent = ItemsControl.ItemsControlFromItemContainer(this) as TreeListViewItem; | |
_level = (parent != null) ? parent.Level + 1 : 0; | |
return _level; | |
} | |
} | |
public TreeListViewItem(object header) | |
{ | |
Header = header; | |
} | |
public TreeListViewItem(){} | |
protected override DependencyObject GetContainerForItemOverride() | |
{ | |
return new TreeListViewItem(); | |
} | |
protected override bool IsItemItsOwnContainerOverride(object item) | |
{ | |
return item is TreeListViewItem; | |
} | |
} | |
public class LevelToIndentConverter : IValueConverter | |
{ | |
private const double c_IndentSize = 19.0; | |
public object Convert(object o, Type type, object parameter,CultureInfo culture) | |
{ | |
return new Thickness((int)o * c_IndentSize, 0, 0, 0); | |
} | |
public object ConvertBack(object o, Type type, object parameter,CultureInfo culture) | |
{ | |
throw new NotSupportedException(); | |
} | |
} | |
} | |
"@ -ReferencedAssemblies presentationFramework,PresentationCore,WindowsBase,System.Xaml -ErrorAction SilentlyContinue | |
## form layout | |
[xml]$xaml = @" | |
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:s='clr-namespace:System;assembly=mscorlib' | |
xmlns:l='clr-namespace:_treeListView;assembly=$([_treeListView.LevelToIndentConverter].Assembly)' | |
Title="TreeListView" Width="640" Height="480"> | |
<Window.Resources> | |
<Style x:Key="ExpandCollapseToggleStyle" | |
TargetType="{x:Type ToggleButton}"> | |
<Setter Property="Focusable" Value="False"/> | |
<Setter Property="Width" Value="19"/> | |
<Setter Property="Height" Value="13"/> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="{x:Type ToggleButton}"> | |
<Border Width="19" Height="13" Background="Transparent"> | |
<Border Width="9" Height="9" BorderThickness="1" BorderBrush="#FF7898B5" CornerRadius="1" SnapsToDevicePixels="true"> | |
<Border.Background> | |
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> | |
<LinearGradientBrush.GradientStops> | |
<GradientStop Color="White" Offset=".2"/> | |
<GradientStop Color="#FFC0B7A6" Offset="1"/> | |
</LinearGradientBrush.GradientStops> | |
</LinearGradientBrush> | |
</Border.Background> | |
<Path x:Name="ExpandPath" Margin="1,1,1,1" Fill="Black" | |
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> | |
</Border> | |
</Border> | |
<ControlTemplate.Triggers> | |
<Trigger Property="IsChecked" Value="True"> | |
<Setter Property="Data" TargetName="ExpandPath" Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> | |
</Trigger> | |
</ControlTemplate.Triggers> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
<l:LevelToIndentConverter x:Key="LevelToIndentConverter"/> | |
<DataTemplate x:Key="CellTemplate_Name"> | |
<DockPanel> | |
<ToggleButton x:Name="Expander" | |
Style="{StaticResource ExpandCollapseToggleStyle}" | |
Margin="{Binding Level, Converter={StaticResource LevelToIndentConverter}, | |
RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" | |
IsChecked="{Binding Path=IsExpanded, RelativeSource= | |
{RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" | |
ClickMode="Press"/> | |
<TextBlock Text="{Binding Name}"/> | |
</DockPanel> | |
<DataTemplate.Triggers> | |
<DataTrigger Binding="{Binding Path=HasItems,RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" Value="False"> | |
<Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> | |
</DataTrigger> | |
</DataTemplate.Triggers> | |
</DataTemplate> | |
<GridViewColumnCollection x:Key="gvcc"> | |
<GridViewColumn Header="Name" CellTemplate="{StaticResource CellTemplate_Name}" /> | |
<GridViewColumn Header="MemberType" DisplayMemberBinding="{Binding MemberType}" /> | |
<GridViewColumn Header="Definition" DisplayMemberBinding="{Binding Definition}" /> | |
<GridViewColumn Header="Value" DisplayMemberBinding="{Binding Value}" /> | |
</GridViewColumnCollection> | |
<Style TargetType="{x:Type l:TreeListViewItem}"> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="{x:Type l:TreeListViewItem}"> | |
<StackPanel> | |
<Border Name="Bd" | |
Background="{TemplateBinding Background}" | |
BorderBrush="{TemplateBinding BorderBrush}" | |
BorderThickness="{TemplateBinding BorderThickness}" | |
Padding="{TemplateBinding Padding}"> | |
<GridViewRowPresenter x:Name="PART_Header" | |
Content="{TemplateBinding Header}" | |
Columns="{StaticResource gvcc}" /> | |
</Border> | |
<ItemsPresenter x:Name="ItemsHost" /> | |
</StackPanel> | |
<ControlTemplate.Triggers> | |
<Trigger Property="IsExpanded" Value="false"> | |
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/> | |
</Trigger> | |
<MultiTrigger> | |
<MultiTrigger.Conditions> | |
<Condition Property="HasHeader" Value="false"/> | |
<Condition Property="Width" Value="Auto"/> | |
</MultiTrigger.Conditions> | |
<Setter TargetName="PART_Header" Property="MinWidth" Value="75"/> | |
</MultiTrigger> | |
<MultiTrigger> | |
<MultiTrigger.Conditions> | |
<Condition Property="HasHeader" Value="false"/> | |
<Condition Property="Height" Value="Auto"/> | |
</MultiTrigger.Conditions> | |
<Setter TargetName="PART_Header" Property="MinHeight" Value="19"/> | |
</MultiTrigger> | |
<Trigger Property="IsSelected" Value="true"> | |
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> | |
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> | |
</Trigger> | |
<MultiTrigger> | |
<MultiTrigger.Conditions> | |
<Condition Property="IsSelected" Value="true"/> | |
<Condition Property="IsSelectionActive" Value="false"/> | |
</MultiTrigger.Conditions> | |
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> | |
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> | |
</MultiTrigger> | |
<Trigger Property="IsEnabled" Value="false"> | |
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> | |
</Trigger> | |
</ControlTemplate.Triggers> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
<Style TargetType="{x:Type l:TreeListView}"> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="{x:Type l:TreeListView}"> | |
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> | |
<DockPanel> | |
<GridViewHeaderRowPresenter Columns="{StaticResource gvcc}" DockPanel.Dock="Top"/> | |
<ScrollViewer CanContentScroll="True"> | |
<Grid> | |
<ItemsPresenter/> | |
</Grid> | |
</ScrollViewer> | |
</DockPanel> | |
</Border> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
</Window.Resources> | |
<l:TreeListView x:Name="Tlv"/> | |
</Window> | |
"@ | |
$rootVariableName = dir variable:\* -Exclude InputObject,Args | | |
Where-Object { | |
$_.Value -and | |
($_.Value.GetType() -eq $InputObject.GetType()) -and | |
($_.Value.GetHashCode() -eq $InputObject.GetHashCode()) | |
} | |
## If we got multiple, pick the first | |
$rootVariableName = $rootVariableName| % Name | Select -First 1 | |
## If we didn't find one, use a default name | |
if(-not $rootVariableName) | |
{ | |
$rootVariableName = "InputObject" | |
} | |
## A function to add an object to the display tree | |
function PopulateNode($node, $object) | |
{ | |
## If we've been asked to add a NULL object, just return | |
if(-not $object) { return } | |
## If the object is a collection, then we need to add multiple | |
## children to the node | |
if([System.Management.Automation.LanguagePrimitives]::GetEnumerator($object)) | |
{ | |
## Some very rare collections don't support indexing (i.e.: $foo[0]). | |
## In this situation, PowerShell returns the parent object back when you | |
## try to access the [0] property. | |
#$isOnlyEnumerable = $object.GetHashCode() -eq $object[0].GetHashCode() | |
## Go through all the items | |
$count = 0 | |
foreach($childObjectValue in $object) | |
{ | |
## Create the new node to add, with the node text of the item and | |
## value, along with its type | |
$newChildNode = New-Object _treeListView.TreeListViewItem | |
#make sure the string version of it isnt more than a single line. | |
$showValue = if(($arr="$childObjectValue" -split "\n" | ?{$_}).count -gt 1) | |
{ | |
"$($arr[0].trim()) ..." | |
} | |
else | |
{ | |
"$childObjectValue" | |
} | |
$newChildNode.ToolTip = "$childObjectValue" | |
$newChildNode.Header = [pscustomobject] @{ | |
Name=$childObjectValue.GetType().name | |
Value="$showValue" | |
Definition=$childObjectValue.gettype() | |
MemberType="Collection" | |
} | |
## Use the node name to keep track of the actual property name | |
## and syntax to access that property. | |
## If we can't use the index operator to access children, add | |
## a special tag that we'll handle specially when displaying | |
## the node names. | |
if($isOnlyEnumerable) | |
{ | |
$newChildNode.Tag = "@" | |
} | |
$newChildNode.Tag += "[$count]" | |
$null = $node.Items.Add($newChildNode) | |
## If this node has children or properties, add a placeholder | |
## node underneath so that the node shows a '+' sign to be | |
## expanded. | |
AddPlaceholderIfRequired $newChildNode $childObjectValue | |
$count++ | |
} | |
} | |
else | |
{ | |
## If the item was not a collection, then go through its | |
## properties | |
$members = Get-Member -InputObject $object | |
foreach($member in $members) | |
{ | |
$childNode = New-Object _treeListView.TreeListViewItem | |
$memberValue = if($member.MemberType -like "*Propert*") | |
{ | |
$prop = $object.($member.Name) | |
if($prop) | |
{ | |
$prop | |
$childnode.ToolTip = $prop | |
$namespace = $prop.gettype().fullname -split '\.' | |
if($namespace[0] -ne "system" -or $namespace.count -gt 2 ) | |
{ | |
AddPlaceholderIfRequired $childNode $prop | |
} | |
} | |
else { '$null' } | |
} | |
elseif($member.MemberType -eq "Method") | |
{ | |
$childNode.ToolTip = ($object.($member.name) | Out-String).trim() | |
} | |
$showValue = if(($arr="$memberValue" -split "\n"|?{$_}).count -gt 1) | |
{ | |
"$($arr[0].trim()) ..." | |
} | |
else | |
{ | |
"$memberValue" | |
} | |
$childNode.Header = [pscustomobject] @{ | |
Name=$member.name | |
Value=$showValue | |
Definition=$member.Definition | |
MemberType=$member.MemberType | |
} | |
$childNode.Tag = $member.Name | |
$null = $node.Items.Add($childNode) | |
} | |
} | |
} | |
## A function to add a placeholder if required to a node. | |
## If there are any properties or children for this object, make a temporary | |
## node with the text "..." so that the node shows a '+' sign to be | |
## expanded. | |
function AddPlaceholderIfRequired($node, $object) | |
{ | |
if(-not $object) { return } | |
if([System.Management.Automation.LanguagePrimitives]::GetEnumerator($object) -or | |
@($object.PSObject.Properties)) | |
{ | |
$null = $node.Items.Add( (New-Object _treeListView.TreeListViewItem ([pscustomobject]@{Name="..."}) ) ) | |
} | |
} | |
## A function invoked when a node is selected. | |
function OnSelect | |
{ | |
param($Sender, $TreeViewEventArgs) | |
## Determine the selected node | |
$nodeSelected = $TreeViewEventArgs.source | |
## Walk through its parents, creating the virtual | |
## PowerShell syntax to access this property. | |
$nodePath = GetPathForNode $nodeSelected | |
## Now, invoke that PowerShell syntax to retrieve | |
## the value of the property. | |
$resultObject = Invoke-Expression $nodePath | |
#$outputPane.Text = $nodePath | |
## If we got some output, put the object's member | |
## information in the text box. | |
if($resultObject) | |
{ | |
$members = Get-Member -InputObject $resultObject | Out-String | |
#$outputPane.Text += "`n" + $members | |
} | |
} | |
## A function invoked when the user is about to expand a node | |
function OnExpand | |
{ | |
param($Sender, $TreeViewCancelEventArgs) | |
## Determine the selected node | |
$selectedNode = $TreeViewCancelEventArgs.Source | |
## If it has a child node that is the placeholder, clear | |
## the placeholder node. | |
if($selectedNode.items.Count -eq 1 -and | |
($selectedNode.Items[0].Header.Name-eq "...")) | |
{ | |
$selectedNode.items.Clear() | |
} | |
else | |
{ | |
return | |
} | |
## Walk through its parents, creating the virtual | |
## PowerShell syntax to access this property. | |
$nodePath = GetPathForNode $selectedNode | |
$global:nodepath= $nodePath | |
## Now, invoke that PowerShell syntax to retrieve | |
## the value of the property. | |
Invoke-Expression "`$resultObject = $nodePath" | |
## And populate the node with the result object. | |
PopulateNode $selectedNode $resultObject | |
} | |
## A function to handle keypresses on the form. | |
## In this case, we capture ^C to copy the path of | |
## the object property that we're currently viewing. | |
function OnKeyPress | |
{ | |
param($Sender, $KeyPressEventArgs) | |
## [Char] 3 = Control-C | |
if($KeyPressEventArgs.KeyChar -eq 3) | |
{ | |
$KeyPressEventArgs.Handled = $true | |
## Get the object path, and set it on the clipboard | |
$node = $Sender.SelectedNode | |
$nodePath = GetPathForNode $node | |
[System.Windows.Forms.Clipboard]::SetText($nodePath) | |
$form.Close() | |
} | |
} | |
## A function to walk through the parents of a node, | |
## creating virtual PowerShell syntax to access this property. | |
function GetPathForNode | |
{ | |
param($Node) | |
$nodeElements = @() | |
## Go through all the parents, adding them so that | |
## $nodeElements is in order. | |
while($Node.Tag) | |
{ | |
$nodeElements = ,$Node + $nodeElements | |
$Node = $Node.Parent | |
} | |
## Now go through the node elements | |
$nodePath = "" | |
foreach($Node in $nodeElements) | |
{ | |
$nodeName = $Node.Tag | |
## If it was a node that PowerShell is able to enumerate | |
## (but not index), wrap it in the array cast operator. | |
if($nodeName.StartsWith('@')) | |
{ | |
$nodeName = $nodeName.Substring(1) | |
$nodePath = "@(" + $nodePath + ")" | |
} | |
elseif($nodeName.StartsWith('[')) | |
{ | |
## If it's a child index, we don't need to | |
## add the dot for property access | |
} | |
elseif($nodePath) | |
{ | |
## Otherwise, we're accessing a property. Add a dot. | |
$nodePath += "." | |
} | |
## Append the node name to the path | |
$nodePath += $nodeName | |
} | |
## And return the result | |
$nodePath | |
} | |
## Create the TreeView, which will hold our object navigation | |
## area. | |
$reader=(New-Object System.Xml.XmlNodeReader $xaml) | |
$Form=[Windows.Markup.XamlReader]::Load( $reader ) | |
$tlv = $Form.FindName('Tlv') | |
[System.Windows.RoutedEventHandler]$Script:Select = { OnSelect @args } | |
[System.Windows.RoutedEventHandler]$Script:Expand = { OnExpand @args } | |
[System.Windows.RoutedEventHandler]$Script:KeyPress = { OnKeyPress @args } | |
$tlv.AddHandler([_treeListView.TreeListViewItem]::SelectedEvent, $Script:Select) | |
$tlv.AddHandler([_treeListView.TreeListViewItem]::ExpandedEvent, $Script:Expand) | |
$tlv.AddHandler([_treeListView.TreeListViewItem]::KeyUpEvent, $Script:KeyPress) | |
## Create the root node, which represents the object | |
## we are trying to show. | |
$root = New-Object _treeListView.TreeListViewItem ([pscustomobject]@{ | |
Name=$InputObject.gettype().name | |
Value="$InputObject" | |
Definition=$InputObject.gettype().fullname}) | |
#root.Header = "$InputObject : " + $InputObject.GetType() | |
$root.Tag = '$' + $rootVariableName | |
$root.ToolTip = "$InputObject" | |
$root.IsExpanded = $true | |
#$null = $treeView.Nodes.Add($root) | |
## And populate the initial information into the tree | |
## view. | |
PopulateNode $root $InputObject | |
$null = $tlv.Items.Add($root) | |
$null = $Form.ShowDialog() | |
## Finally, create the main form and show it. | |
} | |
#gps | Show-Object |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | |
add-type @" | |
using System; | |
using System.Windows.Controls; | |
using System.Windows; | |
using System.Windows.Data; | |
using System.Globalization; | |
namespace _treeListView | |
{ | |
public class TreeListView : TreeView | |
{ | |
protected override DependencyObject GetContainerForItemOverride() | |
{ | |
return new TreeListViewItem(); | |
} | |
protected override bool IsItemItsOwnContainerOverride(object item) | |
{ | |
return item is TreeListViewItem; | |
} | |
} | |
public class TreeListViewItem : TreeViewItem | |
{ | |
private int _level = -1; | |
public int Level | |
{ | |
get | |
{ | |
if (_level != -1) return _level; | |
var parent = ItemsControl.ItemsControlFromItemContainer(this) as TreeListViewItem; | |
_level = (parent != null) ? parent.Level + 1 : 0; | |
return _level; | |
} | |
} | |
public TreeListViewItem(object header) | |
{ | |
Header = header; | |
} | |
public TreeListViewItem(){} | |
protected override DependencyObject GetContainerForItemOverride() | |
{ | |
return new TreeListViewItem(); | |
} | |
protected override bool IsItemItsOwnContainerOverride(object item) | |
{ | |
return item is TreeListViewItem; | |
} | |
} | |
public class LevelToIndentConverter : IValueConverter | |
{ | |
private const double c_IndentSize = 19.0; | |
public object Convert(object o, Type type, object parameter,CultureInfo culture) | |
{ | |
return new Thickness((int)o * c_IndentSize, 0, 0, 0); | |
} | |
public object ConvertBack(object o, Type type, object parameter,CultureInfo culture) | |
{ | |
throw new NotSupportedException(); | |
} | |
} | |
} | |
"@ -ReferencedAssemblies presentationFramework,PresentationCore,WindowsBase,System.Xaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$names="MemberType","Definition","Value" | |
$primaryField = "Name" | |
$p = gps | select -first 1 | |
$pProp = $p | gm -MemberType Properties | |
$root = new-object _treeListView.TreeListViewItem ([pscustomobject]@{Name=$p.gettype().name;Value="$_";Type=$p.gettype().fullname}) | |
foreach($prop in $pProp) | |
{ | |
$data = [pscustomobject] @{ | |
Name=$prop.Name | |
Value=$p.($prop.Name) | |
Definition=$prop.Definition | |
MemberType=$prop.MemberType | |
} | |
$null= $root.Items.Add( (New-Object _treeListView.TreeListViewItem $data)) | |
} | |
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | |
$primaryField = "Name" | |
$fields = ($names | %{ | |
"<GridViewColumn Header=`"$_`" DisplayMemberBinding=`"{Binding $_}`" />" | |
} ) -join "`n" | |
[xml]$xaml = @" | |
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:s='clr-namespace:System;assembly=mscorlib' | |
xmlns:l='clr-namespace:_treeListView;assembly=$([_treeListView.LevelToIndentConverter].Assembly)' | |
Title="TreeListView" Width="640" Height="480"> | |
<Window.Resources> | |
<Style x:Key="ExpandCollapseToggleStyle" | |
TargetType="{x:Type ToggleButton}"> | |
<Setter Property="Focusable" Value="False"/> | |
<Setter Property="Width" Value="19"/> | |
<Setter Property="Height" Value="13"/> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="{x:Type ToggleButton}"> | |
<Border Width="19" Height="13" Background="Transparent"> | |
<Border Width="9" Height="9" BorderThickness="1" BorderBrush="#FF7898B5" CornerRadius="1" SnapsToDevicePixels="true"> | |
<Border.Background> | |
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> | |
<LinearGradientBrush.GradientStops> | |
<GradientStop Color="White" Offset=".2"/> | |
<GradientStop Color="#FFC0B7A6" Offset="1"/> | |
</LinearGradientBrush.GradientStops> | |
</LinearGradientBrush> | |
</Border.Background> | |
<Path x:Name="ExpandPath" Margin="1,1,1,1" Fill="Black" | |
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> | |
</Border> | |
</Border> | |
<ControlTemplate.Triggers> | |
<Trigger Property="IsChecked" Value="True"> | |
<Setter Property="Data" TargetName="ExpandPath" Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> | |
</Trigger> | |
</ControlTemplate.Triggers> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
<l:LevelToIndentConverter x:Key="LevelToIndentConverter"/> | |
<DataTemplate x:Key="CellTemplate_Name"> | |
<DockPanel> | |
<ToggleButton x:Name="Expander" | |
Style="{StaticResource ExpandCollapseToggleStyle}" | |
Margin="{Binding Level, Converter={StaticResource LevelToIndentConverter}, | |
RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" | |
IsChecked="{Binding Path=IsExpanded, RelativeSource= | |
{RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" | |
ClickMode="Press"/> | |
<TextBlock Text="{Binding Name}"/> | |
</DockPanel> | |
<DataTemplate.Triggers> | |
<DataTrigger Binding="{Binding Path=HasItems,RelativeSource={RelativeSource AncestorType={x:Type l:TreeListViewItem}}}" Value="False"> | |
<Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> | |
</DataTrigger> | |
</DataTemplate.Triggers> | |
</DataTemplate> | |
<GridViewColumnCollection x:Key="gvcc"> | |
<GridViewColumn Header="Name" CellTemplate="{StaticResource CellTemplate_Name}" /> | |
<GridViewColumn Header="MemberType" DisplayMemberBinding="{Binding MemberType}" /> | |
<GridViewColumn Header="Definition" DisplayMemberBinding="{Binding Definition}" /> | |
<GridViewColumn Header="Value" DisplayMemberBinding="{Binding Value}" /> | |
</GridViewColumnCollection> | |
<Style TargetType="{x:Type l:TreeListViewItem}"> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="{x:Type l:TreeListViewItem}"> | |
<StackPanel> | |
<Border Name="Bd" | |
Background="{TemplateBinding Background}" | |
BorderBrush="{TemplateBinding BorderBrush}" | |
BorderThickness="{TemplateBinding BorderThickness}" | |
Padding="{TemplateBinding Padding}"> | |
<GridViewRowPresenter x:Name="PART_Header" | |
Content="{TemplateBinding Header}" | |
Columns="{StaticResource gvcc}" /> | |
</Border> | |
<ItemsPresenter x:Name="ItemsHost" /> | |
</StackPanel> | |
<ControlTemplate.Triggers> | |
<Trigger Property="IsExpanded" Value="false"> | |
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/> | |
</Trigger> | |
<MultiTrigger> | |
<MultiTrigger.Conditions> | |
<Condition Property="HasHeader" Value="false"/> | |
<Condition Property="Width" Value="Auto"/> | |
</MultiTrigger.Conditions> | |
<Setter TargetName="PART_Header" Property="MinWidth" Value="75"/> | |
</MultiTrigger> | |
<MultiTrigger> | |
<MultiTrigger.Conditions> | |
<Condition Property="HasHeader" Value="false"/> | |
<Condition Property="Height" Value="Auto"/> | |
</MultiTrigger.Conditions> | |
<Setter TargetName="PART_Header" Property="MinHeight" Value="19"/> | |
</MultiTrigger> | |
<Trigger Property="IsSelected" Value="true"> | |
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> | |
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> | |
</Trigger> | |
<MultiTrigger> | |
<MultiTrigger.Conditions> | |
<Condition Property="IsSelected" Value="true"/> | |
<Condition Property="IsSelectionActive" Value="false"/> | |
</MultiTrigger.Conditions> | |
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> | |
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> | |
</MultiTrigger> | |
<Trigger Property="IsEnabled" Value="false"> | |
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> | |
</Trigger> | |
</ControlTemplate.Triggers> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
<Style TargetType="{x:Type l:TreeListView}"> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="{x:Type l:TreeListView}"> | |
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> | |
<DockPanel> | |
<GridViewHeaderRowPresenter Columns="{StaticResource gvcc}" DockPanel.Dock="Top"/> | |
<ItemsPresenter/> | |
</DockPanel> | |
</Border> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
</Window.Resources> | |
<l:TreeListView x:Name="Tlv"/> | |
</Window> | |
"@ | |
$reader=(New-Object System.Xml.XmlNodeReader $xaml) | |
$Form=[Windows.Markup.XamlReader]::Load( $reader ) | |
#$i = New-Object _treeListView.TreeListViewItem | |
#$i.Header = (gps)[0].GetType() | |
$tlv = $Form.FindName('Tlv') | |
$null = $tlv.Items.Add($root) | |
$Form.ShowDialog() | |
[_treeListView.TreeListView]::select |
@hernandezjesus thanks for the update! this was mostly designed to be run from ISE ages ago. I'll have to play around to see if i can make this smart enough to work in a few different setups (ISE/powershell.exe/pwsh.exe)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I was getting an assembly dependency version error with PowerShell 7.3.* which solves by using the $PwshPath dll