Ограничение WPF, даже если оно не требуется - как его отключить?

Мне нужно выложить некоторый контент из ListBox как указано в DataTemplate для ListBox.ItemTemplate, я использую RenderTransform но содержание обрезается ListBox границы. ClipToBounds является False для всего визуального дерева.

Я где-то читал, что WPF внутренне выполняет некоторое отсечение, даже когда ни одно не указано с выделенными свойствами отсечения. Я также узнал, что с помощью Canvas иногда может вылечить проблему отсечения, но здесь это не поможет.

Как я могу преодолеть эту проблему? Вот некоторые XAML, которые я хочу исправить. Обратите внимание, что вся левая часть прямоугольника отсутствует.

    <ListBox>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Rectangle Fill="Red" Stroke="Green" StrokeThickness="4" Width="100" Height="50">
                    <Rectangle.RenderTransform>
                        <TranslateTransform X="-50" />
                    </Rectangle.RenderTransform>
                </Rectangle>
            </DataTemplate>
        </ListBox.ItemTemplate>

        42
    </ListBox>

2 ответа

Решение

ListBoxItemобрезаем ScrollViewer в ListBox Шаблон. Чтобы обойти это, я думаю, вам нужно удалить ScrollViewer из шаблона и, если вам нужна прокрутка, вы можете обернуть ListBox в ScrollViewer

<ScrollViewer HorizontalScrollBarVisibility="Auto"
              VerticalScrollBarVisibility="Auto">
    <ListBox Margin="100,10,0,0">
        <ListBox.Template>
            <ControlTemplate TargetType="{x:Type ListBox}">
                <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </ListBox.Template>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Rectangle Fill="Red" Stroke="Green" StrokeThickness="4" Width="100" Height="50">
                    <Rectangle.RenderTransform>
                        <TranslateTransform X="-50" />
                    </Rectangle.RenderTransform>
                </Rectangle>
            </DataTemplate>
        </ListBox.ItemTemplate> 42
    </ListBox>
</ScrollViewer>

Обновить

ScrollViewer в шаблоне сгенерирует ScrollContentPresenter который в свою очередь имеет следующее GetLayoutClip

protected override Geometry GetLayoutClip(Size layoutSlotSize)
{
    return new RectangleGeometry(new Rect(base.RenderSize));
}

Этот класс запечатан, поэтому вы не можете использовать его для переопределения этого метода. Вы должны были бы реализовать свой собственный ScrollContentPresenter (например MyScrollContentPresenter) и, вероятно, ваш собственный ScrollViewer который использует MyScrollContentPresenter а также сделать эту работу (и если вы вернетесь null в этом методе я думаю, что некоторые пункты ниже границ ListBox может стать заметным)

Я наткнулся на решение этой проблемы случайно, работая вокруг нее. Если вы измените ScrollViewer's HorizontalScrollMode и VerticalScrollMode на "Disabled" в шаблоне стиля, он прекратит отсечение в каждом направлении соответственно.

Изменить: Может не работать для WPF. Я тестировал с приложением UWP. Рассматриваемые поля:

ScrollViewer.HorizontalScrollMode = "Выключено"

ScrollViewer.VerticalScrollMode = "Выключено"

Другие вопросы по тегам