来自Base64的图像不会显示在WPF数据网格行中

时间:2017-10-11 09:37:52

标签: wpf powershell datagrid

我尝试使用Powershell在WPF数据网格中每行的开头添加一个图标。我不想存储图像,因此我使用base64进行转换。

以下是显示带有图标+进程名称的数据网格的代码:

Add-Type -AssemblyName PresentationFramework, System.Windows.Forms, System.Drawing
[xml]$xaml=@"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow" Height="410" Width="670" WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid x:Name="dgResults" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Icon" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image x:Name="icon" Source="{Binding Icon}" Width="24" Height="24" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Binding="{Binding Process}" Header="Process" IsReadOnly="True"/>
    </DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
"@

$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load($reader)

$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'x:Name')]]") | ForEach-Object{
    Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name)
}

#start conversion
$strBase64 = [convert]::ToBase64String([System.Drawing.Icon]::ExtractAssociatedIcon("C:\windows\System32\cmd.exe"))
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($strBase64)
$bitmap.EndInit()
$bitmap.Freeze()
#end conversion

$arrayItems = @()

Get-Process | Select-Object Name -First 5 | ForEach-Object{
    $itemObject = New-Object System.Object
    $itemObject | Add-Member -Type NoteProperty -Name "Icon" -Value $bitmap
    $itemObject | Add-Member -Type NoteProperty -Name "Process" -Value $_.Name
    $arrayItems += $itemObject
}

$dgResults.ItemsSource = $arrayItems

#Display Form
$Window.ShowDialog() | Out-Null

Base64字符串的转换在这里完成:

#start conversion
$strBase64 = [convert]::ToBase64String([System.Drawing.Icon]::ExtractAssociatedIcon("C:\windows\System32\cmd.exe"))
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($strBase64)
$bitmap.EndInit()
$bitmap.Freeze()
#end conversion

$bitmap对象返回System.Windows.Media.Imaging.BitmapImage

当我使用$Window.Icon = $bitmap更改窗口徽标时,没有问题,图标设置正确,但是当我存储它并使用来自ItemsSource的{​​{1}}来调用数据时(包含图标+进程名称),图像不会出现在每行的开头。

你有什么想法吗?

感谢。

使用基于@ArcSet答案的函数进行更新:

$arrayItems

1 个答案:

答案 0 :(得分:1)

所以这个问题与WPF如何真正支持图标格式有关。您需要将该格式转换为WPF Image标签可读的格式。请改用以下代码。您正在使用的是什么

Add-Type -AssemblyName PresentationFramework, System.Windows.Forms, System.Drawing
[xml]$xaml=@"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow" Height="410" Width="670" WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid x:Name="dgResults" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Icon" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image x:Name="icon" Source="{Binding Icon}" Width="24" Height="24" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Binding="{Binding Process}" Header="Process" IsReadOnly="True"/>
    </DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
"@

$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load($reader)

$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'x:Name')]]") | ForEach-Object{
    Set-Variable -Name ($_.Name) -Value $Window.FindName($_.Name)
}

#start conversion
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("C:\windows\System32\cmd.exe")
$bmp = $icon.ToBitmap()
$stream = new-object System.IO.MemoryStream
$bmp.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
$imageSource = [System.Windows.Media.Imaging.BitmapFrame]::Create($stream);
#end conversion

$arrayItems = @()

Get-Process | Select-Object Name -First 5 | ForEach-Object{
    $itemObject = New-Object System.Object
    $itemObject | Add-Member -Type NoteProperty -Name "Icon" -Value $imageSource
    $itemObject | Add-Member -Type NoteProperty -Name "Process" -Value $_.Name
    $arrayItems += $itemObject
}

$dgResults.ItemsSource = $arrayItems
#Display Form
$Window.ShowDialog() | Out-Null

区别在于转换为PNG ......

$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("C:\windows\System32\cmd.exe")
$bmp = $icon.ToBitmap()
$stream = new-object System.IO.MemoryStream
$bmp.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
$imageSource = [System.Windows.Media.Imaging.BitmapFrame]::Create($stream);