3

WPFから継承するカスタムキャンバスコントロールを作成しましたCanvas。私はメインウィンドウでこのように使用しています-

<ScrollViewer
    HorizontalScrollBarVisibility="Auto"
    VerticalScrollBarVisibility="Auto">
    <RTD:RTDesignerCanvas
        Margin="5"
        Background="White"
        x:Name="canvas1"
        Focusable="True"
        AllowDrop="True">
    </RTD:RTDesignerCanvas>
</ScrollViewer>

すべて正常に動作しますが、このように内部のコントロールの位置を設定しようとすると

Canvas.SetTop(item, 200);

スクロールバーは表示されず、コントロールはどこかに隠されています。興味深いことに、それに別のコントロールを追加すると、スクロールバーが表示され、下にスクロールして前のコントロールを表示できます。

使ってみました

base.InvalidateVisual();
base.UpdateLayout();
base.InvalidateArrange();

アイテムを変更した後、TopまたはLeft何も起こりません。何かが足りないのですか、それともバグが原因で発生しますか?

更新

明確にするために、たとえば100、100のキャンバスがあるとしますwidthheightこれを使用してコントロール(すでにキャンバスに追加されています)をCanvas.SetLeft(myControl, 200)移動すると、デフォルトでは表示されない位置に移動し、スクロールバーも無効になります。そのコントロールを確認する方法はありません。

これで、Canvasに別のコントロールを追加すると、ScrollBarが正しく表示され、スクロールすると前のコントロールを確認できます。

4

3 に答える 3

8

カスタムCanvasでMeasureOverrideをオーバーライドしましたか?Canvasは常に(0、0)のDesiredSizeを報告するため、ScrollViewerはスクロールする必要があるとは決して考えません。

Canvasの代わりにGridを使用し、配置にMarginプロパティを使用することを提案するこのStackOverflowの回答を参照してください。グリッドは子のサイズと位置に基づいてサイズを報告するため、ScrollViewerはスクロールする必要があることを認識します。

アップデート:

ScrollViewerは、子に必要なサイズを要求し、子がScrollViewerよりも大きい場合にのみスクロールする必要があります。正しくスクロールするには、すべての子コントロールを含めるのに十分な大きさのDesiredSizeを報告する必要があります。これを行うには、次のようにMeasureOverrideをオーバーライドします。

protected override Size MeasureOverride(Size constraint)
{
    base.MeasureOverride(constraint);
    var desiredSize = new Size();
    foreach (UIElement child in Children)
    {
        desiredSize = new Size(
            Math.Max(desiredSize.Width, GetLeft(child) + child.DesiredSize.Width),
            Math.Max(desiredSize.Height, GetTop(child) + child.DesiredSize.Height));
    }
    return desiredSize;
}

ただし、より簡単な解決策は、Gridクラスがすでにこのように測定されるという事実を利用することです。Canvas.LeftプロパティとCanvas.Topプロパティの代わりに、子要素のMarginプロパティを使用してそれらを正確に配置できます。あなたが現在やっているなら

Canvas.SetLeft(item, 100);
Canvas.SetTop(item, 200);

キャンバス内のアイテムの場合、代わりに次のことができます

item.Margin = new Thickness(100, 200, 0, 0);

1セルグリッド内の同じ場所に配置します。

于 2010-06-17T12:58:58.090 に答える
1

クォーターマイスターの答えは、この問題を解決するのに役立ちました。

base.InvalidateMeasure()キャンバスを更新してスクロールバーを表示するには、各操作の後に明示的に使用する必要がありました。

于 2010-07-01T13:55:01.267 に答える
0

Akjoshi、

それはバグでなければなりません。次にキャンバスがどこかに隠れたときに、その上でSnoopを実行し、それがどこにあるかを確認します。次のキャンバスプロパティを確認してください:ActualWidth、、、ActualHeightOpacityVisibility

于 2010-06-17T12:59:54.017 に答える