如何使用 Powershell 在 XAML 数据网格中的列上设置样式属性? [英] How can I set Style properties on a column in an XAML datagrid using Powershell?

查看:26
本文介绍了如何使用 Powershell 在 XAML 数据网格中的列上设置样式属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Powershell 和 XAML 构建 WPF UI.我遇到问题的特定功能是在列上设置样式.我可以在 XAML 中设置样式,但是有 9 列(3 个数据网格中的每列 3 列),所以我觉得在代码中设置属性会更整洁,而不是重复 9 次相同的块.

这是我通过 XAML 在单列上设置样式的方式:

<DataGridTextColumn.ElementStyle><Style TargetType="{x:Type TextBlock}"><Style.Triggers><触发器属性="文本"值=""><Setter Property="Background" Value="LightGreen"/></触发器></Style.Triggers></风格></DataGridTextColumn.ElementStyle></DataGridTextColumn>

这会将空白单元格设置为浅绿色.但是,我更喜欢的方法是在 Powershell 中进行设置.

到目前为止,我已经想出了如何在 Powershell 中手动创建列,如果它们没有显式添加到 XAML 中.我这样做(在绑定到控件之后):

$arrAllDataGrids = @($dataGridUser, $dataGridHome, $dataGridWWID)ForEach($arrAllDataGrids 中的 $objDataGrid){$objDataGrid.AutoGenerateColumns = $false$colAttribute = 新对象 System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Attribute";"绑定" = 新对象 System.Windows.Data.Binding "属性"}$colValue = 新对象 System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Value";"绑定" = 新对象 System.Windows.Data.Binding "值"}$colDate = 新对象 System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Date";"绑定" = 新对象 System.Windows.Data.Binding "日期"}$arrColumns = @($colAttribute, $colValue, $colDate)ForEach ($arrColumns 中的 $objColumn) {$objDataGrid.Columns.Add($objColumn)}}

但是,如果我尝试通过 Powershell 添加样式,我会遇到依赖属性.我尝试通过在 XAML 中创建样式然后尝试在 Powershell 中对其进行逆向工程来检查它们,这就是我迄今为止所制定的:

$dataGridUser.Columns[0].ElementStyle 是 System.Windows.Style 类型$dataGridUser.Columns[0].ElementStyle.Triggers 是 System.Windows.Triggers 类型$dataGridUser.Columns[0].ElementStyle.Triggers.Property 是 Type Selected.System.Windows.Trigger$dataGridUser.Columns[0].ElementStyle.Triggers.Property.Property 是 System.Windows.DependencyProperty 类型

我无法创建 System.Windows.DependencyProperty 类型的对象,该对象应包含 Text 的 Name 属性.到目前为止,我管理的最好的方法是通过 XAML 创建一列,然后像这样提取 Dependency 属性对象:

$objDepend = $($dataGridUser.Columns[0].ElementStyle.Triggers | Select Property).Property

使用此对象,然后我可以创建一个具有正确触发器属性的新列对象(我很欣赏这仍然缺少Setter"属性,但我认为同样的原则将适用),如下所示:

$objSelect = $(New-Object System.Windows.Trigger | 选择属性)$objSelect.Property = $objDepend$objTrigger = 新对象 System.Windows.Trigger$objTrigger.Value = ""$objTrigger.Property = $objSelect.Property$objStyle = 新对象 System.Windows.Style$objStyle.Triggers.Add($objTrigger)$colAttribute = 新对象 System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Attribute";"绑定" = 新对象 System.Windows.Data.Binding "属性";"ElementStyle" = $objStyle}

这显然不是解决这个问题的正确方法,我显然遗漏了一些东西,大概是关于我怀疑是派生而不是简单设置的依赖属性.

我希望一切都有意义,有人可以帮忙吗?

解决方案

我希望回答我自己的(也是唯一的)问题是可以接受的,但我想我会分享我开发的解决方案,以防其他人处于类似情况.

只需编写一个函数来创建 Windows.Style.Object 并将其传回.我已经开始使用两个默认字符串,如下所示:

$strXAMLStart = @"<窗口xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><网格><DataGrid x:Name="dataGridTrigger"><DataGrid.Columns><DataGridTextColumn><DataGridTextColumn.ElementStyle><Style TargetType="{x:Type TextBlock}"><Style.Triggers>`n"@$strXAMLEnd = @"</Style.Triggers></风格></DataGridTextColumn.ElementStyle></DataGridTextColumn></DataGrid.Columns></DataGrid></网格></窗口>"@

因此,该函数使用传递给它的样式参数简要地创建并加载一个 XAML 对象,然后提取该样式对象并将其作为函数的结果传回.然后可以将其应用于 UI 中的列.功能如下:

函数集-ColumnStyle ($hashStyle){添加类型 -AssemblyName PresentationFramework添加类型 -AssemblyName PresentationCore添加类型 -AssemblyName WindowsBase添加类型 -AssemblyName System.Windows.Forms$strXAMLTrigger = $nullForEach($hashStyle.Keys 中的 $key){$strValue = $hashStyle[$key]如果 ($key -eq "Blank") {$strTrigger = ""}否则 {$strTrigger = $key}$strXAMLTrigger += " <Trigger Property="Text`" Value="$strTrigger`">`n"$strXAMLTrigger += " <Setter Property="Background`" Value="$strValue`"/>`n"$strXAMLTrigger += " </Trigger>`n"}[xml]$xamlContent = $strXAMLStart + $strXAMLTrigger + $strXAMLEnd$xamlReader = (New-Object System.Xml.XmlNodeReader $xamlContent)$xamlWindow = [Windows.Markup.XamlReader]::Load($xamlReader)$dataGridTrigger = $xamlWindow.FindName("dataGridTrigger")$objStyle = $dataGridTrigger.Columns[0].ElementStyle返回 $objStyle}

我使用字符串blank"来表示实际的空白单元格,因此如果检测到,则将其替换为".您现在可以调用此函数并将列内容的哈希表传递给所需的颜色,并使用返回的对象设置列的样式:

$hashStyle = @{"Blank" = "#FFFF5050";"0" = "#FF50FF50";"267009" = "#FF50FF50"}$objStyle = Set-ColumnStyle $hashStyle$colDay = 新对象 System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Day";"Binding" = New-Object System.Windows.Data.Binding "Day";"ElementStyle" = $objStyle}$dataGridScripts.Columns.Add($colDay)

希望一切都有意义!

I am building a WPF UI using Powershell and XAML. The particular feature I am having problems with is setting the style on the columns. I am able to set the style within the XAML, but there are 9 columns (3 columns each in 3 data grids) so I feel it would be neater to set the properties in the code rather than repeat the same block 9 times.

This is how I set the style on a single column through XAML:

<DataGridTextColumn Header="Attribute" Binding="{Binding Attribute}">
    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <Trigger Property="Text" Value="">
                    <Setter Property="Background" Value="LightGreen"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

This sets blank cells to light green. However, my preferred method would be to set this in Powershell.

So far I have figured out how to manually create the columns in Powershell if they are not explicitly added in XAML. I do this like so (after binding to the controls):

$arrAllDataGrids = @($dataGridUser, $dataGridHome, $dataGridWWID)
ForEach ($objDataGrid in $arrAllDataGrids)
{
    $objDataGrid.AutoGenerateColumns = $false
    $colAttribute = New-Object System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Attribute"; "Binding" = New-Object System.Windows.Data.Binding "Attribute"}
    $colValue = New-Object System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Value"; "Binding" = New-Object System.Windows.Data.Binding "Value"}
    $colDate = New-Object System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Date"; "Binding" = New-Object System.Windows.Data.Binding "Date"}
    $arrColumns = @($colAttribute, $colValue, $colDate)
    ForEach ($objColumn in $arrColumns) {$objDataGrid.Columns.Add($objColumn)}
}

However, I if I try and add a style through Powershell I come up against Dependency Properties. I've tried to examine them by creating the style in XAML and then trying to reverse engineer it in Powershell, this is what I've worked out so far:

$dataGridUser.Columns[0].ElementStyle is Type System.Windows.Style $dataGridUser.Columns[0].ElementStyle.Triggers is Type System.Windows.Trigger $dataGridUser.Columns[0].ElementStyle.Triggers.Property is Type Selected.System.Windows.Trigger $dataGridUser.Columns[0].ElementStyle.Triggers.Property.Property is Type System.Windows.DependencyProperty

I'm unable to create an object of type System.Windows.DependencyProperty which should hold a Name property of Text. The best I have managed so far is to create one column through XAML and then extract the Dependency property object like this:

$objDepend = $($dataGridUser.Columns[0].ElementStyle.Triggers | Select Property).Property

Using this object, I can then create a new column object with the correct trigger property (I appreciate this is still missing the 'Setter' property but I think the same principles will apply) like this:

$objSelect = $(New-Object System.Windows.Trigger | Select Property)
$objSelect.Property = $objDepend
$objTrigger = New-Object System.Windows.Trigger 
$objTrigger.Value = ""
$objTrigger.Property = $objSelect.Property
$objStyle = New-Object System.Windows.Style
$objStyle.Triggers.Add($objTrigger)
$colAttribute = New-Object System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Attribute"; "Binding" = New-Object System.Windows.Data.Binding "Attribute"; "ElementStyle" = $objStyle}

This is clearly not the right way to go about this though, I am obviously missing something, presumably around Dependency properties which I suspect of being derived rather than simply set.

I hope that all makes sense, can anyone help?

解决方案

I hope it is acceptable to answer my own (and only) question but I thought I would share the solution I developed in case anyone else is in a similar position.

Simply write a function that creates the Windows.Style.Object and passes it back. I've started with two default strings like so:

$strXAMLStart = @"
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <DataGrid x:Name="dataGridTrigger">
            <DataGrid.Columns>
                <DataGridTextColumn>
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Style.Triggers>`n
"@

$strXAMLEnd = @"
                           </Style.Triggers>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
"@

So the function briefly creates and loads an XAML object using the style parameters passed to it and then extracts the style object and passes it back as the result of the function. This can then be applied to the column in the UI. The function is as follows:

Function Set-ColumnStyle ($hashStyle)
{
    Add-Type -AssemblyName PresentationFramework
    Add-Type -AssemblyName PresentationCore
    Add-Type -AssemblyName WindowsBase
    Add-Type -AssemblyName System.Windows.Forms

    $strXAMLTrigger = $null
    ForEach ($key in $hashStyle.Keys)
    {
        $strValue = $hashStyle[$key]
        If ($key -eq "Blank") {$strTrigger = ""}
        Else {$strTrigger = $key}
        $strXAMLTrigger += "                                <Trigger Property=`"Text`" Value=`"$strTrigger`">`n"
        $strXAMLTrigger += "                                    <Setter Property=`"Background`" Value=`"$strValue`"/>`n"
        $strXAMLTrigger += "                                </Trigger>`n"
    }

    [xml]$xamlContent = $strXAMLStart + $strXAMLTrigger + $strXAMLEnd

    $xamlReader = (New-Object System.Xml.XmlNodeReader $xamlContent)
    $xamlWindow = [Windows.Markup.XamlReader]::Load($xamlReader)
    $dataGridTrigger = $xamlWindow.FindName("dataGridTrigger")
    $objStyle = $dataGridTrigger.Columns[0].ElementStyle

    Return $objStyle
}

I've used the string "blank" to represent actual blank cells, so this is replaced by "" if detected. You can now call this function and pass it a hashtable of column contents to desired colours and use the returned object to set the style on the column:

$hashStyle = @{"Blank" = "#FFFF5050"; "0" = "#FF50FF50"; "267009" = "#FF50FF50"}
$objStyle = Set-ColumnStyle $hashStyle
$colDay = New-Object System.Windows.Controls.DataGridTextColumn -Property @{"Header" = "Day"; "Binding" = New-Object System.Windows.Data.Binding "Day"; "ElementStyle" = $objStyle}
$dataGridScripts.Columns.Add($colDay)

Hope that all makes sense!

这篇关于如何使用 Powershell 在 XAML 数据网格中的列上设置样式属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆