2012-03-19 5 views
3

У меня есть ItemsControl, и я хочу, чтобы данные были введены в две колонки. Когда пользователь изменяет размер до меньшей, чем второй столбец, элементы второго столбца должны вставляться в первый столбец. Что-то вроде UniformGrid, но с упаковкой.Как мы можем установить Wrap-точку для WrapPanel?

Мне удалось использовать WrapPanel для этого. Но я вынужден манипулировать и жестко кодировать ItemWidth и MaxWidth WrapPanel для достижения двух элементов столбца и обертывания. Это не очень хорошая практика.

Есть ли способ установить максимальное количество столбцов или другими словами, что позволяет нам решить, в какой момент WrapPanel должен начать упаковку?

Некоторые просмотры в Интернете показали, что WrapGrid в Windows 8 Metro имеет этот property. Кто-нибудь имеет эту реализацию в WPF?

+0

Я думаю, что это как 'WrapPanel' должен работать ... рисовать каждый пункт до следующего пункта не укладывается, а затем переносится на новую строку. Вы должны использовать 'ItemWidth' и' WrapPanel.Width' (или 'MaxWidth'), чтобы сообщить' WrapPanel', когда их следует обернуть. – Rachel

ответ

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

Sweet! Спасибо, Фил. Мне удалось адаптировать это в соответствии с моим требованием. Кстати, есть ли проблемы с производительностью при использовании WrapPanel? –

+0

Я не мог сказать о производительности. Кажется, работает нормально с 30-40 элементами. Вам нужно попробовать. – Phil

+0

Фил, спасибо! – nrkz