使用XSLT 1.0进行XML到XAML的转换排除某些控件的特定转换

时间:2013-02-27 15:26:21

标签: c# xaml xslt xslt-1.0 xsl-stylesheet

假设我有以下XML代码

<PanelWrapper   id="RootPanel" 
                width="800" 
                height="600" 
                forecolor="Black">
    <ButtonWrapper  id="button" 
                    text="click!" 
                    forecolor="Black">
        <TabIndex>0</TabIndex>
        <TabStop>True</TabStop>
    </ButtonWrapper>
</PanelWrapper>

应使用XSLT 1.0将此代码转换为XAML代码:

<WrapPanel Name="RootPanel" 
           Width="800" 
           Height="600">
    <Button Name="button" 
            Content="click!" 
            Foreground="Black"  
            TabIndex="0" 
            IsTabStop="True">
    </Button>
</WrapPanel>

我目前正在使用此样式表:(简化版)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <!-- Transform PanelWrapper to WrapPannel -->
    <xsl:template match="PanelWrapper">
        <WrapPanel>
            <xsl:apply-templates select="@*|*" />
        </WrapPanel>
    </xsl:template>

    <!-- Transform ButtonWrapper to Button -->
    <xsl:template match="ButtonWrapper">
        <Button>
            <xsl:apply-templates select="@*" />
        </Button>
    </xsl:template>

    <!-- some other mapping for id(name), height, weight, text -->

    <!-- Map forecolor to Foreground -->
    <xsl:template match="@forecolor">
        <xsl:attribute name="Foreground">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

我目前得到的结果如下:

<WrapPanel Name="RootPanel" 
           Width="800" 
           Height="600"
           Foreground="Black"> //unwanted, Problem 1
    <Button Name="button" 
            Content="click!" 
            Foreground="Black">
    </Button>
            0 //Problem 2
        True //Problem 2
</WrapPanel>

问题1: XAML中的WrapPanel没有Foreground属性,但由于我的XML源文件中定义了forecolor,因此它也是为WrapPanel生成的。我怎么解决这个问题?

问题2: 如何解决TabIndex和IsTabStop的问题?

编辑:让我澄清问题2。 这是xml输入:

<ButtonWrapper  id="button" 
                text="click!" 
                forecolor="Black">
    <TabIndex>0</TabIndex>
    <TabStop>True</TabStop>
</ButtonWrapper>

这是我试图实现的输出:

<Button Name="button" 
        Content="click!" 
        Foreground="Black"  
        TabIndex="0" 
        IsTabStop="True">
</Button>

2 个答案:

答案 0 :(得分:1)

问题1 。您可以添加以下模板

<xsl:template match="PanelWrapper/@forecolor" />

将为所有PanelWrapper元素排除名为forecolor的属性。

问题2 。要解决第二个问题,您必须分别使用以下XPath表达式匹配所有TabIndex元素和TabStop元素,这些元素是某个元素的子元素:* / TabIndex,* / TabStop。然后,您可以将该元素映射到属性。

以下转型可实现您的目标:

<!-- Transform element TabIndex to an attribute with the same
     name in its parent -->
<xsl:template match="*/TabIndex">
    <xsl:attribute name="TabIndex">
        <xsl:value-of select="." />
    </xsl:attribute>
</xsl:template>

<!-- Transform element TabStop to an attribute with the name
     IsTabStop in its parent -->
<xsl:template match="*/TabStop">
    <xsl:attribute name="IsTabStop">
        <xsl:value-of select="." />
    </xsl:attribute>
</xsl:template>

更新。添加了完整XML的解决方案。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <!-- 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,isTabIndex|dock,DockPanel.Dock|width,Width|height,Height|'" />

    <!--                        -->
    <!-- Default processing     -->
    <!--                        -->

    <!-- 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>

    <!--                        -->
    <!-- Control transformations-->
    <!--                        -->

    <!-- 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" />
    <!-- TODO: Exclude doesn't work for the following attributes -->
    <xsl:template match="PanelWrapper/@border-left|PanelWrapper/@border-top|PanelWrapper/@border-right|PanelWrapper/@border-bottom"
                  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>

    <!-- Exclude attributes for ComboBox -->
    <!-- Transform GroupBoxWrapper to GroupBox -->

    <!-- Map GroupBoxWrapper, LabelWrapper, TextBoxWrapper, ButtonWrapper into
         elements with their prefix as their name -->
    <xsl:template match="GroupBoxWrapper|LabelWrapper|TextBoxWrapper|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>

    <!-- Exclude attributes for GroupBox -->
    <!-- Exclude attributes for Label -->
    <!-- Exclude attributes for Text -->
    <!-- TODO: invalid value for Background attribute, eg: Background="window" -->
    <!-- Exclude attributes for Button -->
    <!-- TODO: invalid value for Background attribute, eg: Background="buttonface" -->


    <!-- 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>


    <!-- Exclude attributes for RadioButton -->
    <!-- Exclude attributes for CheckBox -->


    <!--                           -->
    <!-- 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|@dock|@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>

    <!-- OVERRIDE!! Back color: not sure of the logic here.-->
    <xsl:template match="@backcolor" mode="to-attr">
        <xsl:attribute name="Background">Grey</xsl:attribute>
    </xsl:template>

    <!-- Ignore TabIndex and TabStop within PanelWrapper -->
    <xsl:template match="PanelWrapper/TabIndex|PanelWrapper/TabStop" mode="to-attr" />

    <!-- Map @dock = 'Fill' to @dock = 'Left, Right...etc' -->
    <xsl:template match="@dock[. = 'Fill']"  mode="to-attr" >
        <xsl:attribute name="DockPanel.Dock">
            <xsl:value-of select="'Left, Right, Top, Bottom'" />
        </xsl:attribute>
    </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>

    <!--
    <xsl:template match="@font-style[. = 'Regular']">
        <xsl:attribute name="FontStyle">Normal</xsl:attribute>
    </xsl:template>
    -->
    <!-- TODO: condition is invalid, chooses Italic for everything-->
    <xsl:template match="@font-style"  mode="to-attr">
        <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>

答案 1 :(得分:0)

问题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只接受一个控件,我必须首先将所有属性包装到网格控件中。我认为这没什么大不了的,但事实证明,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>

这是xml文件,应该转换为xaml代码

<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,我欠你至少两杯啤酒