Полосы прокрутки не видны после изменения положения элементов управления внутри холста - PullRequest
2 голосов
/ 17 июня 2010

Я создал пользовательский элемент управления canvas, унаследованный от 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 но ничего не происходит; Я что-то упустил или это происходит из-за какой-то ошибки?

Обновление

, чтобы уточнить, скажем, у меня есть холст, имеющий width, height как 100, 100. Теперь, если я переместу элемент управления (уже добавленный в холст), используя Canvas.SetLeft(myControl, 200), он переместится в положение, которое по умолчанию невидимы, и полосы прокрутки также отключены, поэтому нет никакого способа увидеть этот элемент управления.

Теперь, если я добавлю еще один элемент управления в Canvas, полосы прокрутки появятся правильно, и я смогу увидеть предыдущий элемент управления с помощью прокрутки.

Ответы [ 3 ]

7 голосов
/ 17 июня 2010

Вы переопределили MeasureOverride в своем пользовательском Canvas? Canvas всегда сообщает DesiredSize о (0, 0), поэтому ScrollViewer никогда не будет думать, что ему нужна прокрутка.

См. этот ответ StackOverflow , в котором предлагается использовать Grid вместо Canvas и использовать свойство Margin для позиционирования. Сетка сообщит свой размер в зависимости от размера и положения своих дочерних элементов, поэтому 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 уже будет измерять таким образом. Вы можете использовать свойство Margin дочерних элементов для точного их позиционирования вместо свойств Canvas.Left и Canvas.Top. Если вы в настоящее время делаете

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

для предмета на холсте вы можете вместо этого сделать

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

, чтобы расположить его в том же месте в одной ячейке сетки.

1 голос
/ 01 июля 2010

Ответ Quartermeister помог мне в решении этой проблемы.

Мне приходилось явно использовать base.InvalidateMeasure() после каждой операции, чтобы обновить холст и сделать полосы прокрутки видимыми.

0 голосов
/ 17 июня 2010

Akjoshi,

Должно быть, это ошибка.В следующий раз, когда холст станет где-то скрытым, запустите Snoop и проверьте, где он находится.Обязательно проверьте следующие свойства холста: ActualWidth, ActualHeight, Opacity, Visibility

...