54

スクロールバーが正しい範囲になるようCanvasに、アイテムのサイズに自動的にサイズ変更したいと思います。ScrollViewerこれは XAML で実行できますか?

<ScrollViewer HorizontalScrollBarVisibility="Auto" x:Name="_scrollViewer">
    <Grid x:Name ="_canvasGrid" Background="Yellow">
        <Canvas x:Name="_canvas" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Green"></Canvas>
        <Line IsHitTestVisible="False" .../>
    </Grid>
</ScrollViewer>

上記のコードでは、キャンバスのサイズは常に 0 ですが、子はクリップされません。

4

14 に答える 14

53

いいえ、これは不可能です (以下の MSDN のスニペットを参照してください)。ただし、スクロールバーと自動サイズ変更が必要な場合は、代わりにGridを使用することを検討し、Margin プロパティを使用して項目をこの Grid に配置します。Grid は ScrollViewer に必要な大きさを伝えます。スクロールバー.. Canvas は常に ScrollViewer にサイズは必要ないことを伝えます.. :)

グリッドを使用すると、両方の世界を楽しむことができます - すべての要素を 1 つのセルに配置している限り、任意の配置と自動サイズ調整の両方が得られます。一般に、ほとんどのパネル コントロール (DockPanel、StackPanel など) は Grid コントロールを介して実装できることを覚えておくとよいでしょう。

MSDNから:

キャンバスは、固有のレイアウト特性を持たない唯一のパネル要素です。Canvas が子要素のサイズを自動的に変更する要素の子でない限り、Canvas のデフォルトの Height プロパティと Width プロパティはゼロです。Canvas の子要素はサイズ変更されることはなく、指定された座標に配置されるだけです。これにより、固有のサイズ制約や位置合わせが不要または不要な状況に柔軟に対応できます。子コンテンツを自動的にサイズ変更して配置する場合は、通常、Grid 要素を使用するのが最適です。

お役に立てれば

于 2009-05-14T12:43:01.797 に答える
44

ここでillefの答えをコピーしているだけですが、PilotBobへの答えとして、このようなキャンバスオブジェクトを定義するだけです

public class CanvasAutoSize : Canvas
{
    protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
    {
        base.MeasureOverride(constraint);
        double width = base
            .InternalChildren
            .OfType<UIElement>()
            .Max(i => i.DesiredSize.Width + (double)i.GetValue(Canvas.LeftProperty));

        double height = base
            .InternalChildren
            .OfType<UIElement>()
            .Max(i => i.DesiredSize.Height + (double)i.GetValue(Canvas.TopProperty));

        return new Size(width, height);
    }
}

次に、XAML で CanvasAutoSize を使用します。

            <local:CanvasAutoSize VerticalAlignment="Top" HorizontalAlignment="Left"></local:CanvasAutoSize>

添付されたプロパティを介して機能し、要素に設定するプロパティが少なくて済むため、グリッドを使用する上記のソリューションよりも、このソリューションを好みます。

于 2011-08-19T00:38:43.413 に答える
9

CanvasオーバーライドMeasureOverrideまたはArrangeOverrideメソッドでサイズを変更できると思います。

この仕事は難しくありません。

この投稿を見ることができます。http://illef.tistory.com/entry/Canvas-supports-ScrollViewer

これがお役に立てば幸いです。

ありがとうございました。

于 2010-07-15T08:50:44.617 に答える
6

実行可能な解決策があるようですが、共有したいと思いました。

<Canvas x:Name="topCanvas">
    <Grid x:Name="topGrid" Width="{Binding ElementName=topCanvas, Path=ActualWidth}" Height="{Binding ElementName=topCanvas, Path=ActualHeight}">
        ...Content...
    </Grid>
</Canvas>

上記の手法により、キャンバス内にグリッドをネストし、動的にサイズ変更できます。さらに次元バインディングを使用すると、動的マテリアルを静的マテリアルと混合したり、レイヤリングを実行したりできます。言及しきれないほど多くの可能性があり、いくつかは他よりも難しいものがあります。たとえば、このアプローチを使用して、あるグリッド位置から別のグリッド位置に移動するアニメーション コンテンツをシミュレートします - アニメーションの完了イベントで実際の配置を行います。幸運を。

于 2009-10-30T01:00:23.807 に答える
4
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    autoSizeCanvas(canvas1);
}

void autoSizeCanvas(Canvas canv)
{
    int height = canv.Height;
    int width = canv.Width;
    foreach (UIElement ctrl in canv.Children)
    {
        bool nullTop = ctrl.GetValue(Canvas.TopProperty) == null || Double.IsNaN(Convert.ToDouble(ctrl.GetValue(Canvas.TopProperty))),
                nullLeft = ctrl.GetValue(Canvas.LeftProperty) == null || Double.IsNaN(Convert.ToDouble(ctrl.GetValue(Canvas.LeftProperty)));
        int curControlMaxY = (nullTop ? 0 : Convert.ToInt32(ctrl.GetValue(Canvas.TopProperty))) +
            Convert.ToInt32(ctrl.GetValue(Canvas.ActualHeightProperty)
            ),
            curControlMaxX = (nullLeft ? 0 : Convert.ToInt32(ctrl.GetValue(Canvas.LeftProperty))) +
            Convert.ToInt32(ctrl.GetValue(Canvas.ActualWidthProperty)
            );
        height = height < curControlMaxY ? curControlMaxY : height;
        width = width < curControlMaxX ? curControlMaxX : width;
    }
    canv.Height = height;
    canv.Width = width;
}

関数では、キャンバス内のコントロールが存在できる最大の X 位置と Y 位置を見つけようとしています。

関数は Loaded イベント以降でのみ使用し、コンストラクターでは使用しないでください。ウィンドウは、ロードする前に測定する必要があります..

于 2015-03-18T01:32:06.907 に答える
3

高さ/幅をキャンバス内のコントロールの実際のサイズにバインドすると、うまくいきました。

        <ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
            <Canvas Height="{Binding ElementName=myListBox, Path=ActualHeight}"
                    Width="{Binding ElementName=myListBox, Path=ActualWidth}">
                <ListBox x:Name="myListBox" />
            </Canvas>
        </ScrollViewer>
于 2012-06-20T12:17:14.900 に答える
0

私もこの問題に遭遇しました。私の問題は、オーバーライドされた MeasureOverride 関数のおかげでキャンバスのサイズが変更されたときに、グリッドが自動サイズ変更されなかったことです。

私の問題: WPF MeasureOverride ループ

于 2015-06-09T08:29:31.457 に答える
-2
<viewbox>
    <canvas>
        <uielements /> 
    </canvas>
</viewbox>
于 2010-02-15T05:44:00.830 に答える