13

WPFのコントロールを作成していますが、WPFの達人に質問があります。

サイズ変更可能なウィンドウに合わせてコントロールを拡張できるようにしたい。

私のコントロールには、ウィンドウで展開したいリストボックスがあります。リストボックスの周りに他のコントロール(ボタン、テキストなど)もあります。

コントロールに最小サイズを設定できるようにしたいのですが、コントロールを表示するためのスクロールバーを作成して、ウィンドウのサイズを小さくできるようにしたいのです。

これにより、ネストされたスクロール領域が作成されます。1つはリストボックス用で、もう1つはコントロール全体をラップするScrollViewerです。

これで、リストボックスが自動サイズに設定されている場合、ScrollViewer内で常にフルサイズで描画されるため、スクロールバーが表示されることはありません。

コンテンツを小さくできない場合にのみコントロールをスクロールさせたいのですが、それ以外の場合はコントロールをスクロールしたくありません。代わりに、コントロール内のリストボックスをスクロールしたいと思います。

ScrollViewerクラスのデフォルトの動作を変更するにはどうすればよいですか?ScrollViewerクラスから継承し、MeasureOverrideクラスとArrangeOverrideクラスをオーバーライドしようとしましたが、子を適切に測定して配置する方法がわかりませんでした。アレンジは、実際のコンテンツの子ではなく、何らかの形でScrollContentPresenterに影響を与える必要があるようです。

どんな助け/提案も大歓迎です。

4

7 に答える 7

14

この問題を回避するクラスを作成しました。

public class RestrictDesiredSize : Decorator
{
    Size lastArrangeSize = new Size(double.PositiveInfinity, double.PositiveInfinity);

    protected override Size MeasureOverride(Size constraint)
    {
        Debug.WriteLine("Measure: " + constraint);
        base.MeasureOverride(new Size(Math.Min(lastArrangeSize.Width, constraint.Width),
                                      Math.Min(lastArrangeSize.Height, constraint.Height)));
        return new Size(0, 0);
    }

    protected override Size ArrangeOverride(Size arrangeSize)
    {
        Debug.WriteLine("Arrange: " + arrangeSize);
        if (lastArrangeSize != arrangeSize) {
            lastArrangeSize = arrangeSize;
            base.MeasureOverride(arrangeSize);
        }
        return base.ArrangeOverride(arrangeSize);
    }
}

含まれている要素を大きくしたい場合でも、常に目的のサイズ (0,0) を返します。使用法:

<local:RestrictDesiredSize MinWidth="200" MinHeight="200">
     <ListBox />
</local>
于 2009-10-15T12:09:21.570 に答える
2

ダニエルのソリューションを使用しました。それはうまくいきます。ありがとうございました。

次に、2つのブール依存関係プロパティをデコレータクラスに追加しました:KeepWidthKeepHeight。したがって、新しい機能を1つの次元で抑制することができます。

これには変更が必要ですMeasureOverride

protected override Size MeasureOverride(Size constraint)
{
    var innerWidth = Math.Min(this._lastArrangeSize.Width, constraint.Width);
    var innerHeight = Math.Min(this._lastArrangeSize.Height, constraint.Height);
    base.MeasureOverride(new Size(innerWidth, innerHeight));

    var outerWidth = KeepWidth ? Child.DesiredSize.Width : 0;
    var outerHeight = KeepHeight ? Child.DesiredSize.Height : 0;
    return new Size(outerWidth, outerHeight);
}
于 2012-04-03T07:34:10.583 に答える
2

Control内の にScrollViewerは実質的に無制限のスペースがあるため、問題が発生します。したがって、内部ListBoxでは、すべての要素を表示するために必要な高さ全体を占めることで、スクロールを回避できると考えています。もちろん、あなたの場合、その行動には、アウターを過度に運動させるという望ましくない副作用がありScrollViewerます.

したがって、目的は、十分な高さがある場合は可視ListBoxを使用し、それ以外の場合は特定の最小高を使用するようにすることです。これを実現するための最も直接的な方法は、適切なサイズ(つまり、「通常の」無限大ではなく最小サイズに拡大された指定) を継承してオーバーライドし、 andを使用して見つかった sに渡すことです。ScrollViewerScrollViewerMeasureOverride()availableSizeavailableSizeVisualVisualChildrenCountGetVisualChild(int)

于 2008-10-20T14:13:10.863 に答える
0

外側のスクロールバーを必要とするUIを作成することはお勧めしませんが、これは非常に簡単に実行できます。

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >    
    <ScrollViewer HorizontalScrollBarVisibility="Auto" 
                  VerticalScrollBarVisibility="Auto">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <ListBox Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" MinWidth="200"/>
            <Button Grid.Row="0" Grid.Column="1" Content="Button1"/>
            <Button Grid.Row="1" Grid.Column="1" Content="Button2"/>
            <Button Grid.Row="2" Grid.Column="1" Content="Button3"/>
        </Grid>
    </ScrollViewer>
</Window>

私はこれを本当にお勧めしません。WPFは、グリッドなどの優れたレイアウトシステムを提供します。必要に応じて、アプリのサイズを変更できるようにする必要があります。おそらく、このサイズ変更を防ぐために、ウィンドウ自体にMinWidth / MinHeightを設定できますか?

于 2008-10-13T19:09:29.300 に答える