2012-03-19 21 views
3

ItemsControlがあり、データを2つの列に入力したいとします。ユーザーが2番目の列よりも小さい幅にサイズ変更すると、2番目の列の項目は最初の列に折り返さなければなりません。 UniformGridのようなものですが、折り返しがあります。WrapPanelのラップポイントを設定するにはどうすればよいですか?

私はこれを行うためにWrapPanelを使用することができました。しかし、私は、WrapPanelのItemWidthとMaxWidthを操作してハードコードして、2つのカラムとラップを実現するようにしています。これは良い習慣ではありません。

「列の最大数」を設定する方法はありますか。言い換えれば、WrapPanelが折り返しを開始するポイントを決めることができますか?

インターネットでブラウジングすると、Windows 8 MetroのWrapGridにはpropertyが含まれていることが明らかになりました。誰もWPFでこの実装を持っていますか?

+0

は、ここでは、コードです。 'ItemWidth'と' WrapPanel.Width'(または 'MaxWidth')を使って、' WrapPanel'にラップするタイミングを伝える必要があります。 – Rachel

答えて

4

codeproject.comにはUniformWrapPanelという記事があります。これは、ラップパネル内のアイテムの幅が均一で、ウィンドウの幅に合うように修正されました。最大数の列を持つようにこのコードを簡単に変更することができます。コードを変更してください

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

最大列を指定してください。私はそれが `WrapPanel`が...仕事の次の項目が収まらなくなるまでのすべての項目を描画し、その後、新しい行に折り返すことになっているかと思う

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

甘い! Philに感謝します。私は自分の要求に従ってこれを調整しました。 Btwは、WrapPanelを使用する際にパフォーマンス上の問題はありますか? –

+0

私はパフォーマンスについて言えませんでした。 30-40程度のアイテムでうまく動作するようです。あなたはそれを試す必要があります。 – Phil

+0

フィル、ありがとう! – nrkz

関連する問題