【问题标题】:How can you display a multi-line column header using the Flex Spark Data Grid?如何使用 Flex Spark 数据网格显示多行列标题?
【发布时间】:2011-04-13 20:08:12
【问题描述】:

如何使用 Flex 4.5 的 Flex Spark 数据网格显示多行列标题?

【问题讨论】:

    标签: apache-flex datagrid flex4.5 flex-spark


    【解决方案1】:

    要扩展康斯坦丁的答案,您必须创建一个自定义 HeaderRenderer 并将 LabelmaxDisplayedLines 设置为 2。这是一个 sample renderer I found

    MyRenderer.mxml

    <?xml version="1.0" encoding="utf-8"?>
    
    <!--
    
    ADOBE SYSTEMS INCORPORATED
    Copyright 2010 Adobe Systems Incorporated
    All Rights Reserved.
    
    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.
    
    -->
    
    <!--- 
    
    The DefaultGridHeaderRenderer class defines the default header renderer 
    for the columns of a Spark DataGrid control.
    
    <p>Subclasses defined in MXML can redefine the values of the <code>labelDisplay</code>
    and <code>sortIndicator</code> properties.</p>
    
    @see spark.components.DataGrid
    @see spark.components.GridColumnHeaderGroup
    @see spark.components.gridClasses.GridItemRenderer
    
    @langversion 3.0
    @playerversion Flash 10
    @playerversion AIR 2.0
    @productversion Flex 4.5
    -->
    
    <s:GridItemRenderer minWidth="21" minHeight="21"
                        xmlns:fx="http://ns.adobe.com/mxml/2009" 
                        xmlns:s="library://ns.adobe.com/flex/spark" 
                        xmlns:mx="library://ns.adobe.com/flex/mx">
    
        <fx:Declarations>
            <!--- The default value of the <code>sortIndicator</code> property.
            It must be an IFactory for an IVisualElement.        
    
            <p>This value is specified in a <code>fx:Declaration</code> block and can be overridden
            by a declaration with <code>id="defaultSortIndicator"</code>
            in an MXML subclass.</p>
    
            @langversion 3.0
            @playerversion Flash 10
            @playerversion AIR 2.0
            @productversion Flex 4.5
            -->
            <fx:Component id="defaultSortIndicator">
                <s:Path data="M 3.5 7.0 L 0.0 0.0 L 7.0 0.0 L 3.5 7.0" implements="spark.components.gridClasses.IGridVisualElement">
                    <fx:Script>
                        <![CDATA[
                            import spark.components.DataGrid;
                            import spark.components.Grid;
    
                            /**
                             *  @private
                             */
                            public function prepareGridVisualElement(grid:Grid, rowIndex:int, columnIndex:int):void
                            {
                                const dataGrid:DataGrid = grid.dataGrid;
                                if (!dataGrid)
                                    return;
    
                                const color:uint = dataGrid.getStyle("symbolColor");
                                arrowFill1.color = color;
                                arrowFill2.color = color;
                            }
                        ]]>
                    </fx:Script>
    
                    <s:fill>
                        <s:RadialGradient rotation="90" focalPointRatio="1">    
                            <!--- @private -->
                            <s:GradientEntry id="arrowFill1" color="0" alpha="0.6" />
                            <!--- @private -->
                            <s:GradientEntry id="arrowFill2" color="0" alpha="0.8" />
                        </s:RadialGradient>
                    </s:fill>
                </s:Path>
            </fx:Component>
    
            <!--- Displays the renderer's label property, which is set to the column's <code>headerText</code>.
            It must be an instance of a <code>TextBase</code>, like <code>s:Label</code>.
    
            <p>This visual element is added to the <code>labelDisplayGroup</code> by the renderer's
            <code>prepare()</code> method.   Any size/location constraints specified by the labelDisplay
            define its location relative to the labelDisplayGroup.</p>
    
            <p>This value is specified with a <code>fx:Declaration</code> and can be overridden
            by a declaration with <code>id="labelDisplay"</code>
            in an MXML subclass.</p>
    
    
            @langversion 3.0
            @playerversion Flash 10
            @playerversion AIR 2.0
            @productversion Flex 4.5
            -->
            <s:Label id="labelDisplay" 
                     verticalCenter="1" left="0" right="0" top="0" bottom="0"
                     textAlign="start"
                     fontWeight="bold"
                     verticalAlign="middle"
                     maxDisplayedLines="2"
                     showTruncationTip="true" />
        </fx:Declarations>
    
        <fx:Script>
            <![CDATA[
                import spark.components.gridClasses.IGridVisualElement;
                import mx.core.IVisualElement;
    
                import spark.components.DataGrid;
                import spark.components.GridColumnHeaderGroup;
                import spark.components.gridClasses.GridColumn;
    
                /**
                 *  @private
                 */
                private function dispatchChangeEvent(type:String):void
                {
                    if (hasEventListener(type))
                        dispatchEvent(new Event(type));
                }            
    
                //----------------------------------
                //  maxDisplayedLines
                //----------------------------------
    
                private var _maxDisplayedLines:int = 1;
    
                [Bindable("maxDisplayedLinesChanged")]
                [Inspectable(minValue="-1")]
    
                /**
                 *  The value of this property is used to initialize the 
                 *  <code>maxDisplayedLines</code> property of this renderer's 
                 *  <code>labelDisplay</code> element.
                 * 
                 *  @copy spark.components.supportClasses.TextBase#maxDisplayedLines
                 * 
                 *  @default 1
                 * 
                 *  @langversion 3.0
                 *  @playerversion Flash 10
                 *  @playerversion AIR 1.5
                 *  @productversion Flex 4.5
                 */
                public function get maxDisplayedLines():int
                {
                    return _maxDisplayedLines;
                }
    
                /**
                 *  @private
                 */
                public function set maxDisplayedLines(value:int):void
                {
                    if (value == _maxDisplayedLines)
                        return;
    
                    _maxDisplayedLines = value;
                    if (labelDisplay)
                        labelDisplay.maxDisplayedLines = value;
    
                    invalidateSize();
                    invalidateDisplayList();
    
                    dispatchChangeEvent("maxDisplayedLinesChanged");
                }
    
                //----------------------------------
                //  sortIndicator
                //----------------------------------
    
                private var _sortIndicator:IFactory;
                private var sortIndicatorInstance:IVisualElement;
    
                [Bindable("sortIndicatorChanged")]
    
                /**
                 *  A visual element that's displayed when the column is sorted.
                 * 
                 *  <p>The sortIndicator visual element is added to the <code>sortIndicatorGroup</code>
                 *  by this renderer's <code>prepare()</code> method.  Any size/location constraints 
                 *  specified by the sortIndicator define its location relative to the sortIndicatorGroup.</p>
                 * 
                 *  @default null
                 * 
                 *  @langversion 3.0
                 *  @playerversion Flash 10
                 *  @playerversion AIR 1.5
                 *  @productversion Flex 4.5
                 */
                public function get sortIndicator():IFactory
                {
                    return (_sortIndicator) ? _sortIndicator : defaultSortIndicator;
                }
    
                /**
                 *  @private
                 */
                public function set sortIndicator(value:IFactory):void
                {
                    if (_sortIndicator == value)
                        return;
    
                    _sortIndicator = value;
                    if (sortIndicatorInstance)
                    {
                        sortIndicatorGroup.includeInLayout = false;
                        sortIndicatorGroup.removeElement(sortIndicatorInstance);
                        sortIndicatorInstance = null;
                    }
    
                    invalidateDisplayList();
                    dispatchChangeEvent("sortIndicatorChanged");
                }
    
                /**
                 *  @private
                 *  Create and add the sortIndicator to the sortIndicatorGroup and the 
                 *  labelDisplay into the labelDisplayGroup.
                 */
                override public function prepare(hasBeenRecycled:Boolean):void
                {
                    super.prepare(hasBeenRecycled);
    
                    if (labelDisplay && labelDisplayGroup && (labelDisplay.parent != labelDisplayGroup))
                    {
                        labelDisplayGroup.removeAllElements();
                        labelDisplayGroup.addElement(labelDisplay);
                    }
    
                    const column:GridColumn = this.column;
                    if (sortIndicator && column && column.grid && column.grid.dataGrid && column.grid.dataGrid.columnHeaderGroup)
                    {
                        const dataGrid:DataGrid = column.grid.dataGrid;
                        const columnHeaderGroup:GridColumnHeaderGroup = dataGrid.columnHeaderGroup;
    
                        if (columnHeaderGroup.isSortIndicatorVisible(column.columnIndex))
                        {
                            if (!sortIndicatorInstance)
                            {
                                sortIndicatorInstance = sortIndicator.newInstance();
                                sortIndicatorGroup.addElement(sortIndicatorInstance);
                            }
    
                            // Initialize sortIndicator
                            sortIndicatorInstance.visible = true;
                            const gridVisualElement:IGridVisualElement = sortIndicatorInstance as IGridVisualElement;
                            if (gridVisualElement)
                                gridVisualElement.prepareGridVisualElement(column.grid, -1, column.columnIndex);
    
                            sortIndicatorGroup.includeInLayout = true;
                            sortIndicatorGroup.scaleY = (column.sortDescending) ? 1 : -1;
                        }
                        else
                        {
                            if (sortIndicatorInstance)
                            {
                                sortIndicatorGroup.removeElement(sortIndicatorInstance);
                                sortIndicatorGroup.includeInLayout = false;
                                sortIndicatorInstance = null;
                            }
                        }
                    }
                }
            ]]>
        </fx:Script>
    
        <s:states>
            <s:State name="normal" />
            <s:State name="hovered" />
            <s:State name="down" />
        </s:states>      
    
        <!-- layer 1: shadow -->
        <!--- @private -->
        <s:Rect id="shadow" left="-1" right="-1" top="-1" bottom="-1" radiusX="2">
            <s:fill>
                <s:LinearGradient rotation="90">
                    <s:GradientEntry color="0x000000" 
                                     color.down="0xFFFFFF"
                                     alpha="0.01"
                                     alpha.down="0" />
                    <s:GradientEntry color="0x000000" 
                                     color.down="0xFFFFFF" 
                                     alpha="0.07"
                                     alpha.down="0.5" />
                </s:LinearGradient>
            </s:fill>
        </s:Rect>
    
        <!-- layer 2: fill -->
        <!--- @private -->
        <s:Rect id="fill" left="0" right="0" top="0" bottom="0">
            <s:fill>
                <s:LinearGradient rotation="90">
                    <s:GradientEntry color="0xFFFFFF" 
                                     color.hovered="0xBBBDBD" 
                                     color.down="0xAAAAAA" 
                                     alpha="0.85" />
                    <s:GradientEntry color="0xD8D8D8" 
                                     color.hovered="0x9FA0A1" 
                                     color.down="0x929496" 
                                     alpha="0.85" />
                </s:LinearGradient>
            </s:fill>
        </s:Rect>
    
        <!-- layer 3: fill lowlight -->
        <!--- @private -->
        <s:Rect id="lowlight" left="0" right="0" top="0" bottom="0">
            <s:fill>
                <s:LinearGradient rotation="270">
                    <s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627" />
                    <s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099" />
                    <s:GradientEntry color="0x000000" ratio="0.48001" alpha="0" />
                </s:LinearGradient>
            </s:fill>
        </s:Rect>
    
        <!-- layer 4: fill highlight -->
        <!--- @private -->
        <s:Rect id="highlight" left="0" right="0" top="0" bottom="0">
            <s:fill>
                <s:LinearGradient rotation="90">
                    <s:GradientEntry color="0xFFFFFF"
                                     ratio="0.0"
                                     alpha="0.33" 
                                     alpha.hovered="0.22" 
                                     alpha.down="0.12"/>
                    <s:GradientEntry color="0xFFFFFF"
                                     ratio="0.48"
                                     alpha="0.33"
                                     alpha.hovered="0.22"
                                     alpha.down="0.12" />
                    <s:GradientEntry color="0xFFFFFF"
                                     ratio="0.48001"
                                     alpha="0" />
                </s:LinearGradient>
            </s:fill>
        </s:Rect>  
    
        <!-- layer 5: highlight stroke (all states except down) -->
        <!--- @private -->
        <s:Rect id="highlightStroke" left="0" right="0" top="0" bottom="0" excludeFrom="down">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0xFFFFFF" alpha.hovered="0.22" />
                    <s:GradientEntry color="0xD8D8D8" alpha.hovered="0.22" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
    
        <!-- layer 6: highlight stroke (down state only) -->
        <!--- @private -->
        <s:Rect id="hldownstroke1" left="0" right="0" top="0" bottom="0" includeIn="down">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.0" />
                    <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.001" />
                    <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.0011" />
                    <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.965" />
                    <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.9651" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
        <!--- @private -->
        <s:Rect id="hldownstroke2" left="1" right="1" top="1" bottom="1" includeIn="down">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0x000000" alpha="0.09" ratio="0.0" />
                    <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.0001" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
    
        <s:HGroup left="7" right="7" top="5" bottom="5" gap="8" verticalAlign="middle">
    
            <s:BitmapImage source="54.gif" />
            <!-- layer 7: Container for labelDisplay:TextBase  -->
            <!--- Defines the size and location of the labelDisplay visual element. 
    
            <p>The <code>labelDisplay</code> is added to this Group by the renderer's 
            <code>prepare()</code> method.  Any size/location constraints
            specified by the labelDisplay
            define its layout relative to the labelDisplayGroup.</p>
    
            @langversion 3.0
            @playerversion Flash 10
            @playerversion AIR 2.0
            @productversion Flex 4.5
            -->
            <s:Group id="labelDisplayGroup" width="100%" />
    
            <!-- layer 8: Container for sortIndicator:IVisualElement  -->
            <!--- Defines the size and location of the sortIndicator visual element. 
    
            <p>The <code>sortIndicator</code> is added to this Group by the renderer's 
            <code>prepare()</code> method.  Any size/location constraints specified
            by the sortIndicator
            define its layout relative to the sortIndicatorGroup.  This Group is only
            included in the layout when the sortIndicator is visible.</p>  
    
            @langversion 3.0
            @playerversion Flash 10
            @playerversion AIR 2.0
            @productversion Flex 4.5
            -->
            <s:Group id="sortIndicatorGroup" includeInLayout="false" />
        </s:HGroup>
    
    </s:GridItemRenderer>
    

    然后要在您的 DataGrid 中使用它,只需按照 Constantiner 的示例:

    <s:DataGrid>
        <s:columns>
            <s:ArrayList>
                <s:GridColumn headerRenderer="MyRenderer" />
            </s:ArrayList>
        </s:columns>
    </s:DataGrid>
    

    【讨论】:

    • @Constantiner,我完全错过了关于使用 Spark 数据网格的部分。猜猜我将不得不回到绘图板! :)
    【解决方案2】:

    尝试通过以下方式使用自定义headerRenderer

    <s:DataGrid>
        <s:columns>
            <s:ArrayList>
                <s:GridColumn headerRenderer="MyRenderer" />
            </s:ArrayList>
        </s:columns>
    </s:DataGrid>
    

    单行标题的示例渲染器可以在这里创建{flex4.5 SDK root}/frameworks/projects/spark/src/spark/skins/spark/DefaultGridHeaderRenderer.mxml

    【讨论】:

      【解决方案3】:

      我在使用的 sdk 中没有看到 GridColumn 的 headerRenderer 属性,所以我无法接受其他答案。这是我的解决方案:

      MultiLineColumnHeaderRenderer.mxml:

      <?xml version="1.0" encoding="utf-8"?>
      <s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                      xmlns:s="library://ns.adobe.com/flex/spark" 
                      autoDrawBackground="true">  
          <fx:Script>
              <![CDATA[
                  import spark.components.supportClasses.GridColumn;
              ]]>
          </fx:Script>
          <s:TextArea editable="false" text="{(data as GridColumn).headerText}" />
      </s:ItemRenderer>
      

      带有数据网格的视图中的初始化函数:

              public function init():void{
                  dataGrid.columnHeaderBar.firstItemRenderer = new ClassFactory(MultiLineColumnHeaderRenderer);
                  dataGrid.columnHeaderBar.itemRenderer = new ClassFactory(MultiLineColumnHeaderRenderer);
              }
      

      headerText 中使用&amp;#13; 作为GridColumn:

      <s:GridColumn headerText="Line1&#13;Line2&#13;Line2"/>
      

      【讨论】:

      • 很高兴你知道了。实际上,我的原始答案中有&amp;#13; 部分并将其编辑掉。哈哈
      【解决方案4】:

      制作 DataGridSkin 的副本并将其放置在您的源代码中。然后将第 154 行编辑为此 -

      <fx:Component id="headerRenderer"> 
              <s:DefaultGridHeaderRenderer  maxDisplayedLines="2"/>
      </fx:Component>
      

      希望这会有所帮助,

      丰富

      【讨论】:

        【解决方案5】:

        你必须这样做: - 创建自定义 SparkDatagrid 皮肤,创建默认皮肤的副本 - 创建一个自定义的 DataGrid HeaderRenderer - 只需要新建一个GridItemRenderer(A),把默认DataGridHeaderRenderer的代码放在新建的GridItemRenderer(A)里面 -进入A内的标签“labelDisplay”并将其属性“maxDisplayedLines”从1更改为2 - 现在返回给您自定义 Spark Satagrid 皮肤并搜索“headerRenderer”组件。 - 将其替换为您的自定义 GridItemRender (A) 的实例

        它对我有用...希望对你也有用

        马克

        【讨论】:

          【解决方案6】:

          或者,

          如果您不想仅为 1 个属性创建新的渲染器,您可以像这样设置属性:

          ...
          <s:GridColumn width="100" dataField="myDataField" headerText="myHeaderText">
              <s:headerRenderer>
                  <fx:Component>
                      <s:DefaultGridHeaderRenderer maxDisplayedLines="2" />
                  </fx:Component>
              </s:headerRenderer>
          </s:GridColumn>
          ...
          

          如果您查看DefaultGridHeaderRenderer 组件内的代码,您会看到设置后,它会更改 labelDisplay 中的值

          但是,如果您有很多列,并且长时间放置相同的代码可能会很无聊,只需创建一个扩展 spark Datagrid 的新组件(或根据您的需要嵌套它),然后放置代码:

          public function set columns(value:IList):void
          {
              for each (var gridColumn:GridColumn in value.toArray())
              {
                  var headerRenderer:ClassFactory = new ClassFactory(DefaultGridHeaderRenderer);
                  headerRenderer.properties = {maxDisplayedLines: 2};
                  gridColumn.headerRenderer = headerRenderer;
              }
          
              _columns = value;
          }
          
          [Bindable]
          public function get columns():IList
          {
              return _columns;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-05
            • 2017-01-08
            • 2012-08-16
            • 1970-01-01
            • 2010-09-10
            • 1970-01-01
            相关资源
            最近更新 更多