2009-04-30 80 views
25

我使用WrapPanel作爲ItemsControlItemsPanel。眼下,在控制項目包裝是這樣的:WPF - 如何將所有項目放在WrapPanel中?

|1234567 | 
|890  | 

我希望他們來包裝這樣的:

| 1234567 | 
| 890 | 

概念,佈局過程中應對準項目中的每一線,使得它的集中在WrapPanel的範圍內。

有人可以解釋這可能嗎?

回答

58

內置WrapPanel將不允許您調整其內容 - 只有它本身。這是一種技術,它允許您設置HorizontalContentAlignment

using System; 
using System.Windows; 
using System.Windows.Controls; 

public class AlignableWrapPanel : Panel 
{ 
    public HorizontalAlignment HorizontalContentAlignment 
    { 
     get { return (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); } 
     set { SetValue(HorizontalContentAlignmentProperty, value); } 
    } 

    public static readonly DependencyProperty HorizontalContentAlignmentProperty = 
     DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(HorizontalAlignment.Left, FrameworkPropertyMetadataOptions.AffectsArrange)); 

    protected override Size MeasureOverride(Size constraint) 
    { 
     Size curLineSize = new Size(); 
     Size panelSize = new Size(); 

     UIElementCollection children = base.InternalChildren; 

     for (int i = 0; i < children.Count; i++) 
     { 
      UIElement child = children[i] as UIElement; 

      // Flow passes its own constraint to children 
      child.Measure(constraint); 
      Size sz = child.DesiredSize; 

      if (curLineSize.Width + sz.Width > constraint.Width) //need to switch to another line 
      { 
       panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); 
       panelSize.Height += curLineSize.Height; 
       curLineSize = sz; 

       if (sz.Width > constraint.Width) // if the element is wider then the constraint - give it a separate line      
       { 
        panelSize.Width = Math.Max(sz.Width, panelSize.Width); 
        panelSize.Height += sz.Height; 
        curLineSize = new Size(); 
       } 
      } 
      else //continue to accumulate a line 
      { 
       curLineSize.Width += sz.Width; 
       curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); 
      } 
     } 

     // the last line size, if any need to be added 
     panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); 
     panelSize.Height += curLineSize.Height; 

     return panelSize; 
    } 

    protected override Size ArrangeOverride(Size arrangeBounds) 
    { 
     int firstInLine = 0; 
     Size curLineSize = new Size(); 
     double accumulatedHeight = 0; 
     UIElementCollection children = this.InternalChildren; 

     for (int i = 0; i < children.Count; i++) 
     { 
      Size sz = children[i].DesiredSize; 

      if (curLineSize.Width + sz.Width > arrangeBounds.Width) //need to switch to another line 
      { 
       ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, i); 

       accumulatedHeight += curLineSize.Height; 
       curLineSize = sz; 

       if (sz.Width > arrangeBounds.Width) //the element is wider then the constraint - give it a separate line      
       { 
        ArrangeLine(accumulatedHeight, sz, arrangeBounds.Width, i, ++i); 
        accumulatedHeight += sz.Height; 
        curLineSize = new Size(); 
       } 
       firstInLine = i; 
      } 
      else //continue to accumulate a line 
      { 
       curLineSize.Width += sz.Width; 
       curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); 
      } 
     } 

     if (firstInLine < children.Count) 
      ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, children.Count); 

     return arrangeBounds; 
    } 

    private void ArrangeLine(double y, Size lineSize, double boundsWidth, int start, int end) 
    { 
     double x = 0; 
     if (this.HorizontalContentAlignment == HorizontalAlignment.Center) 
     { 
      x = (boundsWidth - lineSize.Width)/2; 
     } 
     else if (this.HorizontalContentAlignment == HorizontalAlignment.Right) 
     { 
      x = (boundsWidth - lineSize.Width); 
     } 

     UIElementCollection children = InternalChildren; 
     for (int i = start; i < end; i++) 
     { 
      UIElement child = children[i]; 
      child.Arrange(new Rect(x, y, child.DesiredSize.Width, lineSize.Height)); 
      x += child.DesiredSize.Width; 
     } 
    } 
} 
+0

好的一堂,謝謝!如果孩子有一個:https://gist.github.com/gmanny/7450651(只有`ArrangeLine`方法被改變),我已經調整它以尊重`FrameworkElement.Horizo​​ntalAlignment`的價值。 – Gman 2013-11-13 15:13:33

+0

對於拉伸準直: if(i == end - 1 && Horizo​​ntalContentAlignment == Horizo​​ntalAlignment.Stretch) {0128}子面.Arrange(new Rect(x,y,boundsWidth - x,lineSize.Height)); } else child.Arrange(new Rect(x,y,child.DesiredSize.Width,lineSize.Height)); x + = child.DesiredSize.Width; } – Rover 2014-05-26 13:38:22

4

簡單的答案是你不能居中對齊WrapPanel的內容。您可以居中對齊面板本身,但最後一行仍然會在面板中左對齊。

更改建議:

使用帶有行和列的網格。如果您不是動態地將項目添加到集合中,這可以很好地工作。

創建您自己的WrapPanel版本,以您需要的方式工作。 This MSDN document描述了面板如何工作,並且包含了創建自定義面板的章節。它還具有指向示例自定義面板的鏈接。

3

這裏是Silverlight的版本

特別感謝@DTig

using System.Windows.Controls; 
using System.Windows; 
using Telerik.Windows; 
using System; 
using System.Linq; 

public class AlignableWrapPanel : Panel 
{ 
    public HorizontalAlignment HorizontalContentAlignment 
    { 
     get { return (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); } 
     set { SetValue(HorizontalContentAlignmentProperty, value); } 
    } 

    public static readonly DependencyProperty HorizontalContentAlignmentProperty = 
     DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(HorizontalAlignment.Left, FrameworkPropertyMetadataOptions.AffectsArrange)); 

    protected override Size MeasureOverride(Size constraint) 
    { 
     Size curLineSize = new Size(); 
     Size panelSize = new Size(); 

     UIElementCollection children = base.Children; 

     for (int i = 0; i < children.Count; i++) 
     { 
      UIElement child = children[i] as UIElement; 

      // Flow passes its own constraint to children 
      child.Measure(constraint); 
      Size sz = child.DesiredSize; 

      if (curLineSize.Width + sz.Width > constraint.Width) //need to switch to another line 
      { 
       panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); 
       panelSize.Height += curLineSize.Height; 
       curLineSize = sz; 

       if (sz.Width > constraint.Width) // if the element is wider then the constraint - give it a separate line      
       { 
        panelSize.Width = Math.Max(sz.Width, panelSize.Width); 
        panelSize.Height += sz.Height; 
        curLineSize = new Size(); 
       } 
      } 
      else //continue to accumulate a line 
      { 
       curLineSize.Width += sz.Width; 
       curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); 
      } 
     } 

     // the last line size, if any need to be added 
     panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); 
     panelSize.Height += curLineSize.Height; 

     return panelSize; 
    } 

    protected override Size ArrangeOverride(Size arrangeBounds) 
    { 
     int firstInLine = 0; 
     Size curLineSize = new Size(); 
     double accumulatedHeight = 0; 
     UIElementCollection children = this.Children; 

     for (int i = 0; i < children.Count; i++) 
     { 
      Size sz = children[i].DesiredSize; 

      if (curLineSize.Width + sz.Width > arrangeBounds.Width) //need to switch to another line 
      { 
       ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, i); 

       accumulatedHeight += curLineSize.Height; 
       curLineSize = sz; 

       if (sz.Width > arrangeBounds.Width) //the element is wider then the constraint - give it a separate line      
       { 
        ArrangeLine(accumulatedHeight, sz, arrangeBounds.Width, i, ++i); 
        accumulatedHeight += sz.Height; 
        curLineSize = new Size(); 
       } 
       firstInLine = i; 
      } 
      else //continue to accumulate a line 
      { 
       curLineSize.Width += sz.Width; 
       curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); 
      } 
     } 

     if (firstInLine < children.Count) 
      ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, children.Count); 

     return arrangeBounds; 
    } 

    private void ArrangeLine(double y, Size lineSize, double boundsWidth, int start, int end) 
    { 
     double x = 0; 
     if (this.HorizontalContentAlignment == HorizontalAlignment.Center) 
     { 
      x = (boundsWidth - lineSize.Width)/2; 
     } 
     else if (this.HorizontalContentAlignment == HorizontalAlignment.Right) 
     { 
      x = (boundsWidth - lineSize.Width); 
     } 

     UIElementCollection children = Children; 
     for (int i = start; i < end; i++) 
     { 
      UIElement child = children[i]; 
      var rect = new System.Windows.Rect(x, y, child.DesiredSize.Width, lineSize.Height); 
      child.Arrange(rect); 
      x += child.DesiredSize.Width; 
     } 
    } 
} 
4

版本與VerticalContentAlignment(垂直面板):

public class AlignableWrapPanel : Panel { 
    public AlignableWrapPanel() { 
     _orientation = Orientation.Horizontal; 
    } 

    private static bool IsWidthHeightValid(object value) { 
     var v = (double)value; 
     return (double.IsNaN(v)) || (v >= 0.0d && !double.IsPositiveInfinity(v)); 
    } 

    public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register("ItemWidth", typeof(double), 
      typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure), 
      IsWidthHeightValid); 

    [TypeConverter(typeof(LengthConverter))] 
    public double ItemWidth { 
     get { return (double)GetValue(ItemWidthProperty); } 
     set { SetValue(ItemWidthProperty, value); } 
    } 

    public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register("ItemHeight", typeof(double), 
      typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure), 
      IsWidthHeightValid); 

    [TypeConverter(typeof(LengthConverter))] 
    public double ItemHeight { 
     get { return (double)GetValue(ItemHeightProperty); } 
     set { SetValue(ItemHeightProperty, value); } 
    } 

    public static readonly DependencyProperty OrientationProperty = StackPanel.OrientationProperty.AddOwner(typeof(AlignableWrapPanel), 
      new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure, OnOrientationChanged)); 

    public Orientation Orientation { 
     get { return _orientation; } 
     set { SetValue(OrientationProperty, value); } 
    } 

    private static void OnOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
     var p = (AlignableWrapPanel)d; 
     p._orientation = (Orientation)e.NewValue; 
    } 

    private Orientation _orientation; 

    private struct UvSize { 
     internal UvSize(Orientation orientation, double width, double height) { 
      U = V = 0d; 
      _orientation = orientation; 
      Width = width; 
      Height = height; 
     } 

     internal UvSize(Orientation orientation) { 
      U = V = 0d; 
      _orientation = orientation; 
     } 

     internal double U; 
     internal double V; 
     private readonly Orientation _orientation; 

     internal double Width { 
      get { return (_orientation == Orientation.Horizontal ? U : V); } 
      private set { if (_orientation == Orientation.Horizontal) U = value; else V = value; } 
     } 

     internal double Height { 
      get { return (_orientation == Orientation.Horizontal ? V : U); } 
      private set { if (_orientation == Orientation.Horizontal) V = value; else U = value; } 
     } 
    } 

    protected override Size MeasureOverride(Size constraint) { 
     var curLineSize = new UvSize(Orientation); 
     var panelSize = new UvSize(Orientation); 
     var uvConstraint = new UvSize(Orientation, constraint.Width, constraint.Height); 
     var itemWidth = ItemWidth; 
     var itemHeight = ItemHeight; 
     var itemWidthSet = !double.IsNaN(itemWidth); 
     var itemHeightSet = !double.IsNaN(itemHeight); 

     var childConstraint = new Size(
       (itemWidthSet ? itemWidth : constraint.Width), 
       (itemHeightSet ? itemHeight : constraint.Height)); 

     var children = InternalChildren; 

     for (int i = 0, count = children.Count; i < count; i++) { 
      var child = children[i]; 
      if (child == null) continue; 

      //Flow passes its own constrint to children 
      child.Measure(childConstraint); 

      //this is the size of the child in UV space 
      var sz = new UvSize(
        Orientation, 
        (itemWidthSet ? itemWidth : child.DesiredSize.Width), 
        (itemHeightSet ? itemHeight : child.DesiredSize.Height)); 

      if (curLineSize.U + sz.U > uvConstraint.U) { 
       //need to switch to another line 
       panelSize.U = Math.Max(curLineSize.U, panelSize.U); 
       panelSize.V += curLineSize.V; 
       curLineSize = sz; 

       if (!(sz.U > uvConstraint.U)) continue; 
       //the element is wider then the constrint - give it a separate line 
       panelSize.U = Math.Max(sz.U, panelSize.U); 
       panelSize.V += sz.V; 
       curLineSize = new UvSize(Orientation); 
      } else { 
       //continue to accumulate a line 
       curLineSize.U += sz.U; 
       curLineSize.V = Math.Max(sz.V, curLineSize.V); 
      } 
     } 

     //the last line size, if any should be added 
     panelSize.U = Math.Max(curLineSize.U, panelSize.U); 
     panelSize.V += curLineSize.V; 

     //go from UV space to W/H space 
     return new Size(panelSize.Width, panelSize.Height); 
    } 

    protected override Size ArrangeOverride(Size finalSize) { 
     var firstInLine = 0; 
     var itemWidth = ItemWidth; 
     var itemHeight = ItemHeight; 
     double accumulatedV = 0; 
     var itemU = (Orientation == Orientation.Horizontal ? itemWidth : itemHeight); 
     var curLineSize = new UvSize(Orientation); 
     var uvFinalSize = new UvSize(Orientation, finalSize.Width, finalSize.Height); 
     var itemWidthSet = !double.IsNaN(itemWidth); 
     var itemHeightSet = !double.IsNaN(itemHeight); 
     var useItemU = (Orientation == Orientation.Horizontal ? itemWidthSet : itemHeightSet); 

     var children = InternalChildren; 

     for (int i = 0, count = children.Count; i < count; i++) { 
      var child = children[i]; 
      if (child == null) continue; 

      var sz = new UvSize(
        Orientation, 
        (itemWidthSet ? itemWidth : child.DesiredSize.Width), 
        (itemHeightSet ? itemHeight : child.DesiredSize.Height)); 

      if (curLineSize.U + sz.U > uvFinalSize.U) { 
       //need to switch to another line 
       ArrangeLine(finalSize, accumulatedV, curLineSize, firstInLine, i, useItemU, itemU); 

       accumulatedV += curLineSize.V; 
       curLineSize = sz; 

       if (sz.U > uvFinalSize.U) { 
        //the element is wider then the constraint - give it a separate line 
        //switch to next line which only contain one element 
        ArrangeLine(finalSize, accumulatedV, sz, i, ++i, useItemU, itemU); 

        accumulatedV += sz.V; 
        curLineSize = new UvSize(Orientation); 
       } 

       firstInLine = i; 
      } else { 
       //continue to accumulate a line 
       curLineSize.U += sz.U; 
       curLineSize.V = Math.Max(sz.V, curLineSize.V); 
      } 
     } 

     //arrange the last line, if any 
     if (firstInLine < children.Count) { 
      ArrangeLine(finalSize, accumulatedV, curLineSize, firstInLine, children.Count, useItemU, itemU); 
     } 

     return finalSize; 
    } 

    private void ArrangeLine(Size finalSize, double v, UvSize line, int start, int end, bool useItemU, double itemU) { 
     double u; 
     var isHorizontal = Orientation == Orientation.Horizontal; 

     if (_orientation == Orientation.Vertical) { 
      switch (VerticalContentAlignment) { 
       case VerticalAlignment.Center: 
        u = (finalSize.Height - line.U)/2; 
        break; 
       case VerticalAlignment.Bottom: 
        u = finalSize.Height - line.U; 
        break; 
       default: 
        u = 0; 
        break; 
      } 
     } else { 
      switch (HorizontalContentAlignment) { 
       case HorizontalAlignment.Center: 
        u = (finalSize.Width - line.U)/2; 
        break; 
       case HorizontalAlignment.Right: 
        u = finalSize.Width - line.U; 
        break; 
       default: 
        u = 0; 
        break; 
      } 
     } 

     var children = InternalChildren; 
     for (var i = start; i < end; i++) { 
      var child = children[i]; 
      if (child == null) continue; 
      var childSize = new UvSize(Orientation, child.DesiredSize.Width, child.DesiredSize.Height); 
      var layoutSlotU = (useItemU ? itemU : childSize.U); 
      child.Arrange(new Rect(
        isHorizontal ? u : v, 
        isHorizontal ? v : u, 
        isHorizontal ? layoutSlotU : line.V, 
        isHorizontal ? line.V : layoutSlotU)); 
      u += layoutSlotU; 
     } 
    } 

    public static readonly DependencyProperty HorizontalContentAlignmentProperty = DependencyProperty.Register(nameof(HorizontalContentAlignment), typeof(HorizontalAlignment), 
      typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(HorizontalAlignment.Left, FrameworkPropertyMetadataOptions.AffectsArrange)); 

    public HorizontalAlignment HorizontalContentAlignment { 
     get { return (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); } 
     set { SetValue(HorizontalContentAlignmentProperty, value); } 
    } 

    public static readonly DependencyProperty VerticalContentAlignmentProperty = DependencyProperty.Register(nameof(VerticalContentAlignment), typeof(VerticalAlignment), 
      typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(VerticalAlignment.Top, FrameworkPropertyMetadataOptions.AffectsArrange)); 

    public VerticalAlignment VerticalContentAlignment { 
     get { return (VerticalAlignment)GetValue(VerticalContentAlignmentProperty); } 
     set { SetValue(VerticalContentAlignmentProperty, value); } 
    } 
} 
1

我需要一個W rapPanel,可以伸展它的內容,所以基於https://stackoverflow.com/a/7747002/121122和一些擺弄我想出了這個:

public class AlignableWrapPanel : Panel 
{ 
    public HorizontalAlignment HorizontalContentAlignment 
    { 
     get => (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); 
     set => SetValue(HorizontalContentAlignmentProperty, value); 
    } 

    public static readonly DependencyProperty HorizontalContentAlignmentProperty = DependencyProperty.Register(
     nameof(HorizontalContentAlignment), 
     typeof(HorizontalAlignment), 
     typeof(AlignableWrapPanel), 
     new FrameworkPropertyMetadata(HorizontalAlignment.Left, FrameworkPropertyMetadataOptions.AffectsArrange)); 

    protected override Size MeasureOverride(Size constraint) 
    { 
     var curLineSize = new Size(); 
     var panelSize = new Size(); 

     var children = InternalChildren; 

     for (var i = 0; i < children.Count; i++) 
     { 
      var child = children[i]; 

      // flow passes its own constraint to children 
      child.Measure(constraint); 
      var sz = child.DesiredSize; 

      if (curLineSize.Width + sz.Width > constraint.Width) // need to switch to another line 
      { 
       panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); 
       panelSize.Height += curLineSize.Height; 
       curLineSize = sz; 

       if (sz.Width > constraint.Width) // if the element is wider then the constraint - give it a separate line      
       { 
        panelSize.Width = Math.Max(sz.Width, panelSize.Width); 
        panelSize.Height += sz.Height; 
        curLineSize = new Size(); 
       } 
      } 
      else // continue to add to the line 
      { 
       curLineSize.Width += sz.Width; 
       curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); 
      } 
     } 

     // the last line size, if any need to be added 
     panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); 
     panelSize.Height += curLineSize.Height; 

     return panelSize; 
    } 

    protected override Size ArrangeOverride(Size arrangeBounds) 
    { 
     var firstInLine = 0; 
     var curLineSize = new Size(); 
     var accumulatedHeight = 0D; 
     var children = InternalChildren; 

     for (var i = 0; i < children.Count; i++) 
     { 
      var desiredSize = children[i].DesiredSize; 

      if (curLineSize.Width + desiredSize.Width > arrangeBounds.Width) // need to switch to another line 
      { 
       ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, i); 

       accumulatedHeight += curLineSize.Height; 
       curLineSize = desiredSize; 

       if(
        desiredSize.Width > arrangeBounds.Width || 
        children[i] is FrameworkElement element && element.HorizontalAlignment == HorizontalAlignment.Stretch) 
       { 
        // the element is wider then the constraint or it stretches - give it a separate line 
        ArrangeLine(accumulatedHeight, desiredSize, arrangeBounds.Width, i, ++i); 
        accumulatedHeight += desiredSize.Height; 
        curLineSize = new Size(); 
       } 
       firstInLine = i; 
      } 
      else // continue to add to the line 
      { 
       curLineSize.Width += desiredSize.Width; 
       curLineSize.Height = Math.Max(desiredSize.Height, curLineSize.Height); 
      } 
     } 

     if (firstInLine < children.Count) 
     { 
      ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, children.Count); 
     } 

     return arrangeBounds; 
    } 

    private void ArrangeLine(double y, Size lineSize, double boundsWidth, int start, int end) 
    { 
     var children = InternalChildren; 

     var x = 0D; 
     if (HorizontalContentAlignment == HorizontalAlignment.Center) 
     { 
      x = (boundsWidth - lineSize.Width)/2; 
     } 
     else if (HorizontalContentAlignment == HorizontalAlignment.Right) 
     { 
      x = boundsWidth - lineSize.Width; 
     } 

     var stretchChildren = new List<UIElement>(); 
     for (var i = start; i < end; i++) 
     { 
      var child = children[i]; 
      if (child is FrameworkElement element && element.HorizontalAlignment == HorizontalAlignment.Stretch) 
      { 
       stretchChildren.Add(child); 
      } 
     } 

     var spaceAvailableForStretchChildren = boundsWidth - lineSize.Width; 
     var spaceAvailablePerStretchChild = 0D; 
     if (stretchChildren.Any()) 
     { 
      x = 0; // all available space will be filled so start at 0 
      spaceAvailablePerStretchChild = spaceAvailableForStretchChildren/stretchChildren.Count; 
      spaceAvailablePerStretchChild = spaceAvailablePerStretchChild >= 0 ? spaceAvailablePerStretchChild : 0; 
     } 

     for (var i = start; i < end; i++) 
     { 
      var child = children[i]; 
      double itemWidth; 
      if(stretchChildren.Contains(child)) 
      { 
       itemWidth = child.DesiredSize.Width + spaceAvailablePerStretchChild; 
      } 
      else 
      { 
       itemWidth = child.DesiredSize.Width; 
      } 

      child.Arrange(new Rect(x, y, itemWidth, lineSize.Height)); 
      x += itemWidth; 
     } 
    } 
} 
相關問題