我正在开发一个项目,其中有一个 PowerShell 驱动的 UI,其中有一个包含一个选项的树视图列表。我按照这个博客PowerShell WPF - 自定义 TreeView 图标...很棒的文章顺便说一句,该代码运行得很好!我想根据其项目标签为不同文件自定义具有不同图像的树列表。我可以使用 png 图像源和 DataTriggers 让它工作,但是我试图将所有图像作为 SVG 嵌入到画布模板中。我知道如何让它工作的唯一方法是使用 VisualBrush 元素,但我似乎无法让它在 Treeview.resource 框架元素中工作。这是我到目前为止所拥有的:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TreeView"
Height="600" Width="800"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
ShowInTaskbar="False" Topmost="True">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\Icons.xaml" />
<ResourceDictionary Source="Resources\TabControl_LeftSideStyle.xaml" />
<ResourceDictionary Source="Resources\TreeViewItem_StandardStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Window}">
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontWeight" Value="Light" />
<Setter Property="BorderBrush" Value="#004275" />
<Setter Property="BorderThickness" Value="0.5" />
</Style>
<HierarchicalDataTemplate x:Key="CheckBoxItemTemplate" ItemsSource="{Binding Children, Mode=OneTime}">
<StackPanel Orientation="Horizontal">
<CheckBox Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" />
<ContentPresenter Content="{Binding Name, Mode=OneTime}" Margin="2,0" />
</StackPanel>
</HierarchicalDataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Rectangle Fill="#004275" HorizontalAlignment="Left" Height="600" VerticalAlignment="Center" Width="150"/>
<Rectangle Fill="#FFF4F4F5" HorizontalAlignment="Right" Height="600" VerticalAlignment="Center" Width="156"/>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10">
<Image x:Name="_wizMainLogo" Height="48" Width="132" Stretch="Uniform" />
</StackPanel>
<!-- START TAB MENU -->
<TabControl x:Name="_wizTabControl" Style="{DynamicResource TabControlLeftSide}" Width="800" Height="550" HorizontalAlignment="Center" VerticalAlignment="Top">
<TabItem x:Name="_wizid" Header="Tree view" Style="{DynamicResource TabItemsWhite}" Width="150" Margin="0" IsEnabled="False">
<Grid x:Name="TabLayout" Margin="0" Grid.ColumnSpan="2" FocusManager.FocusedElement="{Binding ElementName=tsTree}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="490"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label x:Name="TabMainTitle" Grid.Column="0" HorizontalAlignment="Left" Margin="10,20,0,0" VerticalAlignment="Top" FontSize="22" Content="Tree view list with icons"/>
<Rectangle Grid.Column="0" Fill="HotPink" HorizontalAlignment="Right" Height="40" Width="40" Margin="0,20,13.5,0" VerticalAlignment="Top">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{DynamicResource icons_listoutline}"/>
</Rectangle.OpacityMask>
</Rectangle>
<Label x:Name="TabSubTitle" FontSize="14" HorizontalAlignment="Left" Margin="10,73,0,0" VerticalAlignment="Top" Content="Search for item in list"/>
<TextBox x:Name="TabSearch" HorizontalAlignment="Left" Height="31" Margin="10,103,0,0" TextWrapping="Wrap" Text="Search..." VerticalAlignment="Top" Width="331" Foreground='Gray' VerticalContentAlignment="Center" FontSize="18"/>
<Button x:Name="TabSearchClear" Content="Clear" Height="31" Width="63" HorizontalAlignment="Left" VerticalAlignment="Bottom" FontSize="10" Padding="2" Margin="414,0,0,416" />
<Button x:Name="TabSearchEnter" Content="Search" Height="31" Width="63" HorizontalAlignment="Left" VerticalAlignment="Bottom" FontSize="10" Padding="2" Margin="346,0,0,416" />
<Button x:Name="TabExpand" Content="Expand All" Height="25" Width="113" HorizontalAlignment="Left" VerticalAlignment="Bottom" FontSize="10" Padding="2" Margin="10,0,0,386" />
<Button x:Name="TabCollapse" Content="Collapse All" Height="25" Width="113" HorizontalAlignment="Left" VerticalAlignment="Bottom" FontSize="10" Padding="2" Margin="128,0,0,386" />
<TreeView x:Name="TabTree" HorizontalAlignment="Left" Height="371" Margin="10,169,0,0" VerticalAlignment="Top" Width="467" FontSize="14"
ItemContainerStyle="{StaticResource TreeViewItemStandard}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}" >
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="TreeNodeIMG" Width="20" Height="20" Stretch="Fill">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=Tag[0]}" Value="folder">
<Setter Property="Source" Value="images\folder.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=Tag[0]}" Value="file">
<Setter Property="Source" Value="images\file.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock VerticalAlignment="Center" Text="{Binding}" Margin="5,0" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
<Label Content="More Info" Grid.Column="1" FontSize="14" HorizontalAlignment="Left" Margin="10,31,0,0" VerticalAlignment="Top" Foreground="LightSlateGray" />
<TextBlock x:Name="TabMoreInfo" Grid.Column="1" HorizontalAlignment="Left" Margin="10,89,0,0" Width="136" TextWrapping="Wrap" VerticalAlignment="Top" Height="422">
<Run Text="orem ipsum dolor sit amet, consectetur adipiscing elit. Morbi risus mi, consequat in ultricies eu, euismod nec eros. Pellentesque vel augue sed enim euismod sodales varius a ipsum. "/>
</TextBlock>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
我正在测试的 PowerShell 脚本示例是这样的:
#$ErrorActionPreference='Stop'
##*=============================================
##* VARIABLES
##*=============================================
[string]$ResourceRoot = ($PWD.ProviderPath, $PSScriptRoot)[[bool]$PSScriptRoot]
##*=============================================
##* LOAD UI
##*=============================================
[System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | out-null
function LoadXaml ($filename){
$XamlLoader=(New-Object System.Xml.XmlDocument)
$XamlLoader.Load($filename)
return $XamlLoader
}
$XamlMainWindow=LoadXaml($ResourceRoot+"\MainWindow.xaml")
$reader = (New-Object System.Xml.XmlNodeReader $XamlMainWindow)
$Form = [Windows.Markup.XamlReader]::Load($reader)
$Global:FolderTree = $Form.FindName("TabTree")
##*=============================================
##* MAIN
##*=============================================
$dummyNode = $null
$preselect = 'rootFile1.txt'
$AllFiles = [IO.Directory]::GetFiles("$ResourceRoot\Test")
$AllDirectory = [IO.Directory]::GetDirectories("$ResourceRoot\Test")
# ================== Handle Folders ===========================
#$folder = $AllDirectory[0]
foreach ($folder in $AllDirectory){
$treeViewItem = [Windows.Controls.TreeViewItem]::new()
$treeViewItem.Header = $folder.Substring($folder.LastIndexOf("\") + 1)
$treeViewItem.Tag = @("folder",$folder)
$treeViewItem.Items.Add($dummyNode) | Out-Null
$treeViewItem.Add_Expanded({
Write-Host $_.OriginalSource.Header " is expanded"
TreeExpanded($_.OriginalSource)
})
$FolderTree.Items.Add($treeViewItem)| Out-Null
}
# ================== Handle Files ===========================
foreach ($file in $AllFiles){
$treeViewItem = [Windows.Controls.TreeViewItem]::new()
$treeViewItem.Header = $file.Substring($file.LastIndexOf("\") + 1)
$treeViewItem.Tag = @("file",$file)
$FolderTree.Items.Add($treeViewItem)| Out-Null
If($treeViewItem.Header -eq $preselect){
$treeViewItem.IsSelected = $true
Write-Host ("pre selected Item: {0}" -f $treeViewItem.Header)
}Else{
Write-Host ("Added Item: {0}" -f $treeViewItem.Header)
}
$treeViewItem.Add_PreviewMouseLeftButtonDown({
[System.Windows.Controls.TreeViewItem]$sender = $args[0]
[System.Windows.RoutedEventArgs]$e = $args[1]
Write-Host "Left Click: $($sender.Tag)"
})
$treeViewItem.Add_PreviewMouseRightButtonDown({
[System.Windows.Controls.TreeViewItem]$sender = $args[0]
[System.Windows.RoutedEventArgs]$e = $args[1]
Write-Host "Right Click: $($sender.Tag)"
})
}
Function TreeExpanded($sender){
$global:item = [Windows.Controls.TreeViewItem]$sender
If ($item.Items.Count -eq 1 -and $item.Items[0] -eq $dummyNode)
{
$item.Items.Clear();
Try
{
foreach ($string in [IO.Directory]::GetDirectories($item.Tag[1].ToString()))
{
$subitem = [Windows.Controls.TreeViewItem]::new();
$subitem.Header = $string.Substring($string.LastIndexOf("\") + 1)
$subitem.Tag = @("folder",$string)
$subitem.Items.Add($dummyNode)
$subitem.Add_Expanded({
TreeExpanded($_.OriginalSource)
})
$item.Items.Add($subitem) | Out-Null
}
foreach ($file in [IO.Directory]::GetFiles($item.Tag[1].ToString())){
$subitem = [Windows.Controls.TreeViewItem]::new()
$subitem.Header = $file.Substring($file.LastIndexOf("\") + 1)
$subitem.Tag = @("file",$file)
$item.Items.Add($subitem)| Out-Null
If($subitem.Header -eq $preselect){
$subitem.IsSelected = $true
Write-Host ("pre-selected Item: {0}" -f $subitem.Header)
}Else{
Write-Host ("Added Item: {0}" -f $subitem.Header)
}
$subitem.Add_PreviewMouseLeftButtonDown({
[System.Windows.Controls.TreeViewItem]$sender = $args[0]
[System.Windows.RoutedEventArgs]$e = $args[1]
Write-Host "Left Click: $($sender.Tag)"
})
}
}
Catch [Exception] { }
}
}
##*=============================================
##* SHOW UI
##*=============================================
$Form.ShowDialog() | Out-Null
当我运行代码时,它看起来像这样:
这是根级别文件夹中图像未显示的问题,但没什么大不了的,除非有人也有答案......
画布资源字典文件中有这个:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas x:Key="icon_file" Width="24" Height="24">
<Path Stretch="Fill" Fill="White" Data="M3 5V19H20V5H3M7 7V9H5V7H7M5 13V11H7V13H5M5 15H7V17H5V15M18 17H9V15H18V17M18 13H9V11H18V13M18 9H9V7H18V9Z" />
</Canvas>
<Canvas x:Key="icon_folder" Width="24" Height="24">
<Path Width="20" Height="20" Fill="White" Stretch="Uniform" Data="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z"/>
</Canvas>
</ResourceDictionary>
我让它工作的唯一方法是在 xaml 中使用此代码
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="Green" HorizontalAlignment="Right" Height="20" Width="20" VerticalAlignment="Top">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{DynamicResource icons_folder}"/>
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock Text="{Binding}" Margin="5,0" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
尽管这会将整个图像填充为填充颜色,但它确实会显示,但对于文件夹和文件来说都是相同的。现在,如果我尝试使用画布图像和数据触发器的绑定,则会收到数据类型错误。我在网上没有找到任何关于如何将 svg 数据绑定与树视图和数据触发器结合使用的内容。那里有 C# 编码的分配,但正在寻找 PowerShell 和 .Net 解决方案。
尽管我认为在 XAML 代码中完成此操作会更容易,但我确实尝试在 PowerShell 中以编程方式更改图像......但这也惨败。 有什么想法吗?
我需要你的一些专业技能!谢谢!!!
您可以将
Image
中的 HeaderTemplate
替换为显示您的 ContentControl
资源之一的 Canvas
:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=Tag[0]}" Value="folder">
<Setter Property="Content" Value="{DynamicResource icon_folder}" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=Tag[0]}" Value="file">
<Setter Property="Content" Value="{DynamicResource icon_file}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
<TextBlock VerticalAlignment="Center" Text="{Binding}" Margin="5,0" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>