2012-03-19 33 views
3

我有一個ItemsControl,我想將數據輸入到兩列。當用戶調整到小於第二列的寬度時,第二列的項目必須包裝到第一列中。像一個UniformGrid,但與包裝。我們如何設置WrapPanel的包裹點?

我設法使用WrapPanel來做到這一點。但是我不得不操縱和編寫WrapPanel的ItemWidth和MaxWidth來實現兩列和換行。這不是一個好習慣。

反正是有設定的最大不列或者換句話說,讓我們來決定在什麼時候該WrapPanel應該開始包裝?

在互聯網上的一些瀏覽透露,WrapGrid在Windows 8地鐵有這個property。有沒有人有WPF中的這個實現?

+0

我認爲這是一個'WrapPanel'應該如何工作...繪製每個項目,直到下一個項目不適合,然後換到一個新行。你應該使用'ItemWidth'和'WrapPanel.Width'(或'MaxWidth')來告訴'WrapPanel'何時換行。 – Rachel 2012-03-19 12:51:16

回答

4

在codeproject.com上有一篇UniformWrapPanel文章,我對其進行了修改,以確保包裝面板中的項目具有統一的寬度並適合窗口的寬度。您應該可以輕鬆地修改此代碼以獲得最大數量的列。嘗試更改附近的代碼

var itemsPerRow = (int) (totalWidth/ItemWidth); 

爲了指定最大列數。

下面的代碼:

public enum ItemSize 
{ 
    None, 
    Uniform, 
    UniformStretchToFit 
} 

public class UniformWrapPanel : WrapPanel 
{ 
    public static readonly DependencyProperty ItemSizeProperty = 
     DependencyProperty.Register(
      "ItemSize", 
      typeof (ItemSize), 
      typeof (UniformWrapPanel), 
      new FrameworkPropertyMetadata(
       default(ItemSize), 
       FrameworkPropertyMetadataOptions.AffectsMeasure, 
       ItemSizeChanged)); 

    private static void ItemSizeChanged(
     DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     var uniformWrapPanel = sender as UniformWrapPanel; 
     if (uniformWrapPanel != null) 
     { 
      if (uniformWrapPanel.Orientation == Orientation.Horizontal) 
      { 
       uniformWrapPanel.ItemWidth = double.NaN; 
      } 
      else 
      { 
       uniformWrapPanel.ItemHeight = double.NaN; 
      } 
     } 
    } 

    public ItemSize ItemSize 
    { 
     get { return (ItemSize) GetValue(ItemSizeProperty); } 
     set { SetValue(ItemSizeProperty, value); } 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     var mode = ItemSize; 

     if (Children.Count > 0 && mode != ItemSize.None) 
     { 
      bool stretchToFit = mode == ItemSize.UniformStretchToFit; 

      if (Orientation == Orientation.Horizontal) 
      { 
       double totalWidth = availableSize.Width; 

       ItemWidth = 0.0; 
       foreach (UIElement el in Children) 
       { 
        el.Measure(availableSize); 
        Size next = el.DesiredSize; 
        if (!(Double.IsInfinity(next.Width) || Double.IsNaN(next.Width))) 
        { 
         ItemWidth = Math.Max(next.Width, ItemWidth); 
        } 
       } 

       if (stretchToFit) 
       { 
        if (!double.IsNaN(ItemWidth) && !double.IsInfinity(ItemWidth) && ItemWidth > 0) 
        { 
         var itemsPerRow = (int) (totalWidth/ItemWidth); 
         if (itemsPerRow > 0) 
         { 
          ItemWidth = totalWidth/itemsPerRow; 
         } 
        } 
       } 
      } 
      else 
      { 
       double totalHeight = availableSize.Height; 

       ItemHeight = 0.0; 
       foreach (UIElement el in Children) 
       { 
        el.Measure(availableSize); 
        Size next = el.DesiredSize; 
        if (!(Double.IsInfinity(next.Height) || Double.IsNaN(next.Height))) 
        { 
         ItemHeight = Math.Max(next.Height, ItemHeight); 
        } 
       } 

       if (stretchToFit) 
       { 
        if (!double.IsNaN(ItemHeight) && !double.IsInfinity(ItemHeight) && ItemHeight > 0) 
        { 
         var itemsPerColumn = (int) (totalHeight/ItemHeight); 
         if (itemsPerColumn > 0) 
         { 
          ItemHeight = totalHeight/itemsPerColumn; 
         } 
        } 
       } 
      } 
     } 

     return base.MeasureOverride(availableSize); 
    } 
} 
+0

甜!感謝菲爾。我設法根據我的要求量身定做。順便說一句,有使用WrapPanel的任何性能問題? – 2012-03-20 06:17:18

+0

我不能說性能。似乎可以與30-40左右的項目一起工作。你需要嘗試一下。 – Phil 2012-03-20 06:58:32

+0

菲爾,謝謝! – nrkz 2016-03-24 11:46:24