Выравнивание 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>

Ответы

Ответ 1

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 в шаблоне будет генерировать a ScrollContentPresenter, который, в свою очередь, имеет следующий GetLayoutClip

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

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

Ответ 2

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

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

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

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