问题 1:WrapPanels 仍然显示 BorderThickness [已解决]
解决方案:该模板仅适用于除 PanelWrapper 之外的所有元素。(看条件)
<xsl:template match="@*[starts-with(local-name(), 'border-')][1]" mode="to-attr">
<xsl:if test="not(parent::PanelWrapper)">
<xsl:attribute name="BorderThickness">
<!--Print the border-elements in a comma separated list (non-defined attributes default
to zero)-->
<xsl:call-template name="border-print" />
</xsl:attribute>
</xsl:if>
</xsl:template>
问题 2:由于 WPF 中的组框只接受一个控件,因此我必须首先将所有属性包装到一个网格控件中。我认为这没什么大不了的,但事实证明 groupbox 属性已添加到网格控件中。
这是(更新的)xsl 样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<!-- very special thanks to: Pablo Pozo -->
<xsl:variable name="attributeMap"
select="'|font-size,FontSize|font-name,FontFamily|enabled,isEnabled|forecolor,Foreground|id,Name|TabStop,IsTabStop|TabIndex,TabIndex|dock,DockPanel.Dock|width,Width|height,Height|'" />
<!-- Ignore attributes by default, so we can have more control
about unhandled attributes -->
<xsl:template match="@*|*" />
<xsl:template match="node()|@*" mode="to-attr"/>
<!-- Default attribute processing -->
<xsl:template name="process-element">
<xsl:param name="attr" />
<!-- Process all attributes and elements which are going to be
transformed to attributes -->
<xsl:apply-templates select="@*|*" mode="to-attr" />
<!-- Add extra attribute -->
<xsl:if test="$attr">
<xsl:attribute name="{substring-after($attr, '|')}">
<xsl:value-of select="@*[local-name() = substring-before($attr, '|')]" />
</xsl:attribute>
</xsl:if>
<!-- Process children elements -->
<xsl:apply-templates select="*" />
</xsl:template>
<!-- Transform PanelWrapper to WrapPannel -->
<xsl:template match="PanelWrapper">
<WrapPanel>
<xsl:call-template name="process-element" />
</WrapPanel>
</xsl:template>
<!-- Exclude attributes for PanelWrapper -->
<xsl:template match="PanelWrapper/@forecolor|PanelWrapper/@font-name|PanelWrapper/@font-size|PanelWrapper/@font-style"
mode="to-attr" />
<xsl:template match="PanelWrapper/@border-left|PanelWrapper/@border-top|PanelWrapper/@border-right|PanelWrapper/@border-bottom"
mode="to-attr" />
<xsl:template match="PanelWrapper/TabIndex|PanelWrapper/TabStop"
mode="to-attr" />
<!-- Transform DropDownWrapper to ComboBox -->
<xsl:template match="DropDownWrapper">
<ComboBox>
<xsl:call-template name="process-element">
<xsl:with-param name="attr" select="'text|Text'" />
</xsl:call-template>
</ComboBox>
</xsl:template>
<!-- Map GroupBoxWrapper into
elements with their prefix as their name -->
<xsl:template match="GroupBoxWrapper">
<xsl:element name="GroupBox">
<Grid>
<xsl:call-template name="process-element">
<xsl:with-param name="attr"/>
</xsl:call-template>
</Grid>
</xsl:element>
</xsl:template>
<!-- Map LabelWrapper, ButtonWrapper into
elements with their prefix as their name -->
<xsl:template match="LabelWrapper|ButtonWrapper">
<xsl:element name="{substring-before(local-name(), 'Wrapper')}">
<xsl:call-template name="process-element">
<xsl:with-param name="attr" select="'text|Content'" />
</xsl:call-template>
</xsl:element>
</xsl:template>
<!-- Map TextBoxWrapper into
elements with their prefix as their name -->
<xsl:template match="TextBoxWrapper">
<xsl:element name="{substring-before(local-name(), 'Wrapper')}">
<xsl:call-template name="process-element">
<xsl:with-param name="attr" select="'text|Text'" />
</xsl:call-template>
</xsl:element>
</xsl:template>
<!-- Map RadioButtonViewWrapper, CheckBoxViewWrapper into elements
with their prefix as their name -->
<xsl:template match="RadioButtonViewWrapper|CheckBoxViewWrapper">
<xsl:element name="{substring-before(local-name(), 'ViewWrapper')}">
<xsl:call-template name="process-element">
<xsl:with-param name="attr" select="'text|Content'" />
</xsl:call-template>
</xsl:element>
</xsl:template>
<!-- -->
<!-- Attributes transformations-->
<!-- -->
<!-- Transform elements which just map the name of the attribute to a different name -->
<xsl:template match="@font-size|@font-name|@enabled|@forecolor|@id|TabStop|TabIndex|@width|@height"
mode="to-attr">
<!-- Look in map for the transformation -->
<xsl:variable name="new-attribute"
select="substring-before(substring-after($attributeMap, concat('|', local-name(), ',')), '|')" />
<xsl:attribute name="{$new-attribute}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
<!-- Transform dock element -->
<xsl:template match="@dock" mode="to-attr">
<xsl:choose>
<xsl:when test=". = 'Fill'">
<xsl:attribute name="DockPanel.Dock">
<xsl:value-of select="'Left, Right, Top, Bottom'" />
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:if test=". != 'None'">
<xsl:attribute name="DockPanel.Dock">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Transform Visual Web GUI Colors to XAML conform values.-->
<xsl:template match="@backcolor" mode="to-attr">
<xsl:choose>
<xsl:when test=". = 'buttonface'">
<xsl:attribute name="Background">Azure</xsl:attribute>
</xsl:when>
<xsl:when test=". = 'window'">
<xsl:attribute name="Background">Azure</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="Background">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Map visible attribute to Visibility -->
<xsl:template match="@visible[. = 'True']" mode="to-attr" >
<xsl:attribute name="Visibility">visible</xsl:attribute>
</xsl:template>
<xsl:template match="@visible[. = 'False']" mode="to-attr" >
<xsl:attribute name="Visibility">hidden</xsl:attribute>
</xsl:template>
<!-- Build the border attribute -->
<xsl:template match="@*[starts-with(local-name(), 'border-')][1]" mode="to-attr">
<xsl:attribute name="BorderThickness">
<!-- Print the border-elements in a comma separated list (non-defined attributes default
to zero) -->
<xsl:call-template name="border-print" />
</xsl:attribute>
</xsl:template>
<!-- Recursive template to group borders in BorderThickness -->
<xsl:template name="border-print">
<!-- Do not remove spaces in the next line! -->
<xsl:param name="string" select="'left top right bottom'" />
<xsl:param name="parent" select=".." />
<xsl:param name="not-first" select="false()" />
<xsl:if test="$string != ''">
<!-- Obtain next direction -->
<xsl:variable name="direction" select="normalize-space(substring($string, 1, 6))" />
<xsl:variable name="attr" select="$parent/@*[local-name() = concat('border-', $direction)]" />
<!-- Print comma if not the first element -->
<xsl:if test="$not-first">
<xsl:text>,</xsl:text>
</xsl:if>
<!-- Print zero if the attribute cannot be found -->
<xsl:choose>
<!-- Attribute found : print -->
<xsl:when test="$attr">
<xsl:value-of select="$attr" />
</xsl:when>
<!-- Attribute not found: print 0 -->
<xsl:otherwise>
<xsl:text>0</xsl:text>
</xsl:otherwise>
</xsl:choose>
<!-- Recurse -->
<xsl:call-template name="border-print">
<xsl:with-param name="string" select="substring($string, 7)" />
<xsl:with-param name="parent" select="$parent" />
<xsl:with-param name="not-first" select="true()" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="@*" mode="print-border">
<xsl:value-of select="concat(., ',')" />
</xsl:template>
<xsl:template match="@border-bottom" mode="print-border">
<xsl:value-of select="." />
</xsl:template>
<!-- Mapping font-style to FontStyle -->
<!-- Convert values to valid XAML values -->
<xsl:template match="@font-style">
<xsl:choose>
<xsl:when test=". = 'Italic'">
<xsl:attribute name="FontStyle">Italic</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="FontStyle">Normal</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这是应该转换成xaml代码的xml文件
<PanelWrapper id="RootPanel" dock="Fill" text="" theme="" width="1412" height="605" backcolor="Transparent" forecolor="Black" visible="True" mapNode="" border-left="0" border-top="0" border-right="0" border-bottom="0" font-name="Tahoma" font-size="8,25" font-style="Regular">
<PanelWrapper id="panel1" dock="None" text="" theme="" width="800" height="400" backcolor="Transparent" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<GroupBoxWrapper id="groupbox1" dock="Bottom" text="" theme="" width="796" height="300" backcolor="Transparent" forecolor="#0046D5" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<RadioButtonViewWrapper id="radiobutton1" dock="Top" text="radiobox" theme="" width="484" height="100" backcolor="Transparent" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<TabIndex>1</TabIndex>
<TabStop>True</TabStop>
</RadioButtonViewWrapper>
<CheckBoxViewWrapper id="checkbox1" dock="Left" text="checkbox" theme="" width="75" height="177" backcolor="Transparent" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<TabIndex>2</TabIndex>
<TabStop>True</TabStop>
</CheckBoxViewWrapper>
<TabIndex>4</TabIndex>
<TabStop>False</TabStop>
</GroupBoxWrapper>
<PanelWrapper id="panel5" dock="Top" text="Click!" theme="" width="796" height="25" backcolor="Transparent" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<ButtonWrapper id="button2" dock="Left" text="click!" theme="" width="100" height="21" backcolor="buttonface" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<TabIndex>0</TabIndex>
<TabStop>True</TabStop>
</ButtonWrapper>
<TextBoxWrapper id="textbox2" dock="Left" text="textbox" theme="" width="100" height="21" backcolor="window" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Italic">
<TabIndex>1</TabIndex>
<TabStop>True</TabStop>
</TextBoxWrapper>
<LabelWrapper id="label2" dock="Left" text="label" theme="" width="100" height="21" backcolor="Transparent" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<TabIndex>2</TabIndex>
<TabStop>False</TabStop>
</LabelWrapper>
<DropDownWrapper id="combobox2" dock="Left" text="combobox" theme="" width="100" height="21" backcolor="window" forecolor="Black" visible="True" mapNode="" border-left="1" border-top="1" border-right="1" border-bottom="1" font-name="Tahoma" font-size="9" font-style="Regular">
<TabIndex>3</TabIndex>
<TabStop>True</TabStop>
</DropDownWrapper>
<TabIndex>5</TabIndex>
<TabStop>False</TabStop>
</PanelWrapper>
<TabIndex>0</TabIndex>
<TabStop>False</TabStop>
</PanelWrapper>
<TabIndex>0</TabIndex>
<TabStop>False</TabStop>
</PanelWrapper>
XAML 结果如下所示:
<WrapPanel Name="RootPanel" DockPanel.Dock="Left, Right, Top, Bottom" Width="1412" Height="605" Background="Transparent" Visibility="visible" BorderThickness="0,0,0,0">
<WrapPanel Name="panel1" Width="800" Height="400" Background="Transparent" Visibility="visible" BorderThickness="1,1,1,1">
<GroupBox>
<Grid Name="groupbox1" DockPanel.Dock="Bottom" Width="796" Height="300" Background="Transparent" Foreground="#0046D5" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="4" IsTabStop="False">
<RadioButton Name="radiobutton1" DockPanel.Dock="Top" Width="484" Height="100" Background="Transparent" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="1" IsTabStop="True" Content="radiobox" />
<CheckBox Name="checkbox1" DockPanel.Dock="Left" Width="75" Height="177" Background="Transparent" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="2" IsTabStop="True" Content="checkbox" />
</Grid>
</GroupBox>
<WrapPanel Name="panel5" DockPanel.Dock="Top" Width="796" Height="25" Background="Transparent" Visibility="visible" BorderThickness="1,1,1,1">
<Button Name="button2" DockPanel.Dock="Left" Width="100" Height="21" Background="Azure" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="0" IsTabStop="True" Content="click!" />
<TextBox Name="textbox2" DockPanel.Dock="Left" Width="100" Height="21" Background="Azure" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="1" IsTabStop="True" Text="textbox" />
<Label Name="label2" DockPanel.Dock="Left" Width="100" Height="21" Background="Transparent" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="2" IsTabStop="False" Content="label" />
<ComboBox Name="combobox2" DockPanel.Dock="Left" Width="100" Height="21" Background="Azure" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="3" IsTabStop="True" Text="combobox" />
</WrapPanel>
</WrapPanel>
</WrapPanel>
预期的 XAML 代码应如下所示:
<WrapPanel Name="RootPanel" DockPanel.Dock="Left, Right, Top, Bottom" Width="1412" Height="605" Background="Transparent" Visibility="visible" >
<WrapPanel Name="panel1" Width="800" Height="400" Background="Transparent" Visibility="visible" >
<GroupBox Name="groupbox1" DockPanel.Dock="Bottom" Width="796" Height="300" Background="Transparent" Foreground="#0046D5" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="4" IsTabStop="False">
<Grid>
<RadioButton Name="radiobutton1" DockPanel.Dock="Top" Width="484" Height="100" Background="Transparent" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="1" IsTabStop="True" Content="radiobox" />
<CheckBox Name="checkbox1" DockPanel.Dock="Left" Width="75" Height="177" Background="Transparent" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="2" IsTabStop="True" Content="checkbox" />
</Grid>
</GroupBox>
<WrapPanel Name="panel5" DockPanel.Dock="Top" Width="796" Height="25" Background="Transparent" Visibility="visible" >
<Button Name="button2" DockPanel.Dock="Left" Width="100" Height="21" Background="Azure" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="0" IsTabStop="True" Content="click!" />
<TextBox Name="textbox2" DockPanel.Dock="Left" Width="100" Height="21" Background="Azure" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="1" IsTabStop="True" Text="textbox" />
<Label Name="label2" DockPanel.Dock="Left" Width="100" Height="21" Background="Transparent" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="2" IsTabStop="False" Content="label" />
<ComboBox Name="combobox2" DockPanel.Dock="Left" Width="100" Height="21" Background="Azure" Foreground="Black" Visibility="visible" BorderThickness="1,1,1,1" FontFamily="Tahoma" FontSize="9" TabIndex="3" IsTabStop="True" Text="combobox" />
</WrapPanel>
</WrapPanel>
</WrapPanel>
顺便说一句:Pablo Pozo,我至少欠你两杯啤酒