如何使用Powershell在XAML数据网格中的列上设置样式属性?

时间:2014-02-27 08:31:49

标签: wpf xaml powershell

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

这是我通过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>

这会将空白单元格设置为浅绿色。但是,我首选的方法是在Powershell中设置它。

到目前为止,我已经找到了如何在Powershell中手动创建列,如果它们没有在XAML中明确添加的话。我这样做(在绑定到控件之后):

$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)}
}

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

$ dataGridUser.Columns [0] .ElementStyle是Type System.Windows.Style $ dataGridUser.Columns [0] .ElementStyle.Triggers是Type System.Windows.Trigger $ dataGridUser.Columns [0] .ElementStyle.Triggers.Property是Type Selected.System.Windows.Trigger $ dataGridUser.Columns [0] .ElementStyle.Triggers.Property.Property是Type 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 | 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}

这显然不是解决这个问题的正确方法,我显然遗漏了一些东西,大概是在Dependency属性周围,我怀疑它是派生的而不是简单的设置。

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

1 个答案:

答案 0 :(得分:1)

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

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

$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>
"@

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

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
}

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

$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)

希望一切都有意义!