2014-05-22 83 views
0

我試圖在GridView中顯示多個項目。它主要是因爲它的水平滾動行爲而被選中的。如何通過最大項目設置GridView項目大小

它看起來像GridView定義基礎上,第一個項目尺寸項目大小。在下面的代碼示例中,如果年份從一月開始,則較長的月份名稱會被裁剪,但如果第一個項目較寬,則會按預期顯示名稱。

我也想保持GridView具有相同寬度的所有項目,但一定是最大的一個的寬度。身高也一樣,但在我的情況下,身高是不變的。

有一個相對簡單的方式與GridView實現這一點,也許有這個更合適的控制?


<GridView> 
    <GridView.Items> 
     <x:String>January</x:String> 
     <x:String>February</x:String> 
     <x:String>...</x:String> 
     <x:String>September</x:String> 
     <x:String>October</x:String> 
     <x:String>November</x:String> 
     <x:String>December</x:String> 
    </GridView.Items> 
</GridView> 

GridView output

注:有多個不同的/可變項目大小的例子。不幸的是,這是不是什麼要求。

+0

您可以創建一個自定義'GridView'類(只是從基本'GridView'繼承),它重寫'ArrangeOverride'。在安排物品時,首先測量所有物品(不是每次一個),然後根據最大物品選擇物品尺寸。 –

+0

@Nate Diamond謝謝你,但你能否進一步闡述1-2步?我問的原因是,在調用'ArrangeOverride'期間重新排列項目會導致遞歸佈局更新,幾乎有保證的異常。除此之外,如果我朝這個方向發展,定製'ItemsPanel'容器而不是'GridView'也許會有意義。 –

+0

我不一定要重新安排它們。 ArrangeOverride應該調用每個子項目的安排,傳遞項目將要提供的空間量。因此,這意味着它應該能夠搜索項目的「度量」值(而不是僅使用第一項)並查找其中最大的值。確實,這可以用'Panel'來完成,比如製作一個自定義的'VariableSizeWrapGrid'。 –

回答

0

經過一番研究,以滿足要求最簡單的方法是用在ItemsPanelTemplate自定義面板。

一對夫婦的拒絕方式是
1)擴大GridView:而在GridView導出時,開發人員可以訪問許多有趣的信息,實際的佈局管理是GridView.ItemsPanel控制範圍之外調用執行和修改項目的立場對於一些黑客或脆弱的設計決定。
2)擴大現有ItemPanel容器:這將是最自然的方法,但由於類,如WrapGridVariableSizedWrapGrid是密封的,這是不可能的。

下面是使用定製的面板與GridView的一個例子。
如果項目太少而無法填充整個GridView,則將對齊項設置在左上角而不是中心。
邊距補償滾動條的默認行爲以重疊內容。

<GridView ... > 
    <GridView.ItemsPanel> 
     <ItemsPanelTemplate> 
      <controls:GridViewPanel 
       HorizontalAlignment="Left" 
       VerticalAlignment="Top" 
       Margin="0,0,0,24" /> 
     </ItemsPanelTemplate> 
    </GridView.ItemsPanel> 
    ... 
</GridView> 

甲全定製面板的代碼如下。這是故意簡單化,但它可以很容易地擴展到特定的附加要求,如更精確的佈局控制,可變列寬度,虛擬化等。它沒有經過測試,但具有更高級GridView功能,如分組。

using System; 
using Windows.Foundation; 
using Windows.UI.Xaml.Controls; 

/// <summary> 
/// Uniformly positions child items in columns to present in WrapGrid. 
/// Uses largest item's DesiredSize for item size mesasurements. 
/// Expects limited height and unbound width. 
/// </summary> 
public class GridViewPanel : Panel 
{ 
    protected override Size MeasureOverride(Size availableSize) 
    { 
     return ArrangeInternal(availableSize, callArrange: false); 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     return ArrangeInternal(finalSize); 
    } 

    private Size ArrangeInternal(Size size, bool callArrange = true) 
    { 
     // measure max desired item size 
     // 
     double itemWidth = 0.0, itemHeight = 0.0; 
     foreach (var item in Children) 
     { 
      item.Measure(size); 
      itemWidth = Math.Max(itemWidth, item.DesiredSize.Width); 
      itemHeight = Math.Max(itemHeight, item.DesiredSize.Height); 
     } 
     // requested item height can't exceed total available height 
     itemHeight = Math.Min(itemHeight, size.Height); 

     // position each child and get total content size 
     // 
     double totalWidth = 0.0, totalHeight = 0.0; 
     double x = 0.0, y = 0.0; 

     foreach (var item in Children) 
     { 
      if (y + itemHeight > size.Height) 
      { 
       // if item won't fit, move to the next column 
       totalHeight = Math.Max(totalHeight, y); 
       y = 0; 
       x += itemWidth; 
      } 

      // implicitly, item fits in current column 
      if (callArrange) item.Arrange(new Rect(x, y, itemWidth, itemHeight)); 
      y += itemHeight; 
     } 

     totalWidth = x + itemWidth; 
     totalHeight = Math.Max(totalHeight, y); 

     return new Size(totalWidth, totalHeight); 
    } 
}