3

アイテムをグループで表示するためのリストボックスを作成しました。グループは、リストボックスのパネルの高さに収まらなくなったときに右から左に折り返されます。したがって、グループはリストボックスに次のように表示されます。各グループの高さは任意です(たとえば、グループ1の高さはグループ2の2倍です)。

[ 1 ][ 3 ][ 5 ]
[   ][ 4 ][ 6 ]
[ 2 ][   ]

次のXAMLは、折り返しを実行するという点で正しく機能し、アイテムがリストボックスの右側から実行されたときに水平スクロールバーを表示できるようにします。

<ListBox> 
  <ListBox.ItemsPanel> 
    <ItemsPanelTemplate> 
      <StackPanel Orientation="Vertical"/> 
    </ItemsPanelTemplate> 
  </ListBox.ItemsPanel> 

  <ListBox.GroupStyle> 
    <ItemsPanelTemplate> 
      <WrapPanel Orientation="Vertical" 
                 Height="{Binding Path=ActualHeight, 
                          RelativeSource={RelativeSource 
                            FindAncestor, 
                            AncestorLevel=1, 
                            AncestorType={x:Type ScrollContentPresenter}}}"/> 
    </ItemsPanelTemplate> 
  </ListBox.GroupStyle> 
</ListBox>

この問題は、アイテムのグループがWrapPanelの高さよりも長い場合に発生します。垂直スクロールバーにカットオフアイテムグループを表示させる代わりに、そのグループ内のアイテムは単にクリップされます。これは、WrapPanelのHeightバインディングの副作用であると想定しています。スクロールバーは、有効にする必要はないと考えています。

スクロールバーを有効にする方法、または私が見ないこの問題を回避する別の方法はありますか?

4

4 に答える 4

2

これは少し変更されたコードです - 以前に投稿した Abe Heidebrecht の功績によるものです - 水平スクロールと垂直スクロールの両方を可能にします。唯一の変更点は、MeasureOverride の戻り値を base.MeasureOverride(new Size(ret.width, h)) にする必要があることです。

// Original code : Abe Heidebrecht
public class SmartWrapPanel : WrapPanel
{
  /// <summary>
  /// Identifies the DesiredHeight dependency property
  /// </summary>
  public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register(
    "DesiredHeight",
    typeof(double),
    typeof(SmartWrapPanel),
    new FrameworkPropertyMetadata(Double.NaN, 
            FrameworkPropertyMetadataOptions.AffectsArrange |
            FrameworkPropertyMetadataOptions.AffectsMeasure));

  /// <summary>
  /// Gets or sets the height to attempt to be.  If any child is taller than this, will use the child's height.
  /// </summary>
  public double DesiredHeight
  {
    get { return (double)GetValue(DesiredHeightProperty); }
    set { SetValue(DesiredHeightProperty, value); }
  }

  protected override Size MeasureOverride(Size constraint)
  {
    Size ret = base.MeasureOverride(constraint);
    double h = ret.Height;

    if (!Double.IsNaN(DesiredHeight))
    {
      h = DesiredHeight;
      foreach (UIElement child in Children)
      {
        if (child.DesiredSize.Height > h)
          h = child.DesiredSize.Height;
      }
    }

    return base.MeasureOverride(new Size(ret.Width, h));
  }

  protected override System.Windows.Size ArrangeOverride(Size finalSize)
  {
    double h = finalSize.Height;

    if (!Double.IsNaN(DesiredHeight))
    {
      h = DesiredHeight;
      foreach (UIElement child in Children)
      {
        if (child.DesiredSize.Height > h)
          h = child.DesiredSize.Height;
      }
    }

    return base.ArrangeOverride(new Size(finalSize.Width, h));
  }
}
于 2008-09-17T12:51:19.473 に答える
2

WrapPanel の Height プロパティを ScrollContentPresenter の高さに設定すると、垂直方向にスクロールしなくなります。ただし、その Binding を削除すると、レイアウト パスではレイアウトする無限の高さがあるため、決してラップされません。

独自のパネル クラスを作成して、必要な動作を取得することをお勧めします。目的の高さをバインドできる別の依存関係プロパティを用意して、それを使用してメジャーでターゲットの高さを計算し、ステップを配置できます。1 人の子供が希望の高さよりも背が高い場合は、その子供の高さをターゲットの高さとして使用して、ラッピングを計算します。

これを行うためのパネルの例を次に示します。

public class SmartWrapPanel : WrapPanel
{
    /// <summary>
    /// Identifies the DesiredHeight dependency property
    /// </summary>
    public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register(
        "DesiredHeight",
        typeof(double),
        typeof(SmartWrapPanel),
        new FrameworkPropertyMetadata(Double.NaN, 
            FrameworkPropertyMetadataOptions.AffectsArrange |
            FrameworkPropertyMetadataOptions.AffectsMeasure));

    /// <summary>
    /// Gets or sets the height to attempt to be.  If any child is taller than this, will use the child's height.
    /// </summary>
    public double DesiredHeight
    {
        get { return (double)GetValue(DesiredHeightProperty); }
        set { SetValue(DesiredHeightProperty, value); }
    }

    protected override Size MeasureOverride(Size constraint)
    {
        Size ret = base.MeasureOverride(constraint);
        double h = ret.Height;

        if (!Double.IsNaN(DesiredHeight))
        {
            h = DesiredHeight;
            foreach (UIElement child in Children)
            {
                if (child.DesiredSize.Height > h)
                    h = child.DesiredSize.Height;
            }
        }

        return new Size(ret.Width, h);
    }

    protected override System.Windows.Size ArrangeOverride(Size finalSize)
    {
        double h = finalSize.Height;

        if (!Double.IsNaN(DesiredHeight))
        {
            h = DesiredHeight;
            foreach (UIElement child in Children)
            {
                if (child.DesiredSize.Height > h)
                    h = child.DesiredSize.Height;
            }
        }

        return base.ArrangeOverride(new Size(finalSize.Width, h));
    }
}
于 2008-09-16T17:01:49.503 に答える
0

バインディングに関係しているというあなたの意見は正しいと思います。バインディングを外すとどうなりますか?バインディングで、少なくともリスト ボックスの高さ全体を埋めようとしていますか? その場合は、代わりに MinHeight へのバインドを検討するか、VerticalAlignmentプロパティを使用してみてください。

于 2008-09-16T16:27:27.323 に答える
0

答えてくれてありがとう、デビッド。

バインディングが の場合、removedラッピングは行われません。WrapPanelは、すべてのグループを 1 つの垂直列に配置します。

バインディングは、WrapPanel を実際にラップさせることを目的としています。バインディングが設定されていない場合、WrapPanel は高さが無限であると想定し、ラップしません。

結果にバインドするMinHeightと、空のリストボックスになります。プロパティが解決策のように見えることはわかりますVerticalAlignmentが、配置自体がラッピングの発生を防ぎます。バインドと位置合わせが一緒に使用されている場合、位置合わせは問題に影響しません。

于 2008-09-16T16:36:24.883 に答える