ListBox.ItemTemplate с длинным текстом не соответствует ширине ListBox

Я пытаюсь поместить StackPanel в ListBox, а это в Grid, который является частью UserControl.

Пока что я придумал следующий XAML, но я не могу исправить ширину. Когда вы посмотрите на снимок экрана, вы увидите, что StackPanel на несколько пикселей превышает ширину. Я пробовал HorizontalAlignment=Stretch на каждом элементе, но на Width = {Binding...} удалось ограничить ширину, хотя и не идеально. Что я скучаю?

<UserControl x:Class = "Reusable.Apps.ExceptionControl"
             xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local = "clr-namespace:Reusable.Apps"
             mc:Ignorable = "d" 
             d:DesignHeight = "450" d:DesignWidth = "800" Width = "{Binding (Window.Width), RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type Window}}}">
    <UserControl.Resources>
        <local:ExceptionVisualizerData x:Key = "DesignViewModel" />
        <Style TargetType = "TextBlock" x:Key = "NameStyle">
            <Setter Property = "FontSize" Value = "20"/>
            <Setter Property = "FontWeight" Value = "Bold"/>
            <Setter Property = "FontFamily" Value = "Consolas"/>
            <Setter Property = "Foreground" Value = "DarkMagenta"/>
        </Style>
        <Style TargetType = "TextBlock" x:Key = "MessageStyle">
            <Setter Property = "FontSize" Value = "16"></Setter>
            <Setter Property = "FontFamily" Value = "Segoe UI"/>
            <Setter Property = "TextWrapping" Value = "Wrap"/>
        </Style>
    </UserControl.Resources>
    <Grid Width = "{Binding (UserControl.Width), RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type UserControl}}}">
        <ListBox ItemsSource = "{Binding Exceptions}" d:DataContext = "{Binding Source = {StaticResource DesignViewModel}}" Width = "{Binding (Grid.Width), RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type Grid}}}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel  Width = "{Binding (ListBox.Width), RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type ListBox}}}">
                        <TextBlock Text = "{Binding Name}" Style = "{StaticResource NameStyle}"  />
                        <TextBlock Text = "{Binding Message}" Style = "{StaticResource MessageStyle}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

ListBox.ItemTemplate с длинным текстом не соответствует ширине ListBox

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
112
4

Ответы 4

Вместо обозначения ListBox укажите ширину ListBoxItem.

<StackPanel  Width = "{Binding (ListBoxItem.Width), RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type ListBoxItem}}}">

К сожалению, это не действует :-(

t3chb0t 02.12.2018 13:24

Это сработало в моем местном. Требуется ли ширина привязки? Я имею в виду убрать Ширину с StackPanel и проверить.

Sats 02.12.2018 13:28

На самом деле я нахожу привязку Width уродливой, но это единственный способ сделать это на полпути. Я бы лучше все это выбросил, если бы было что-то получше.

t3chb0t 02.12.2018 13:31

Это было близко. Использование ListBoxItem было хорошим треком, но не в том месте ;-)

t3chb0t 03.12.2018 16:41

Интересно, почему это не сработало, даже если мы связываемся с ListBoxItem.Wdth

Sats 03.12.2018 16:47

Я предполагаю, потому что сам ListBoxItem был слишком широким, поэтому привязка к его Width не решила его (на этот раз?). По всей видимости, он был неограниченной ширины.

t3chb0t 03.12.2018 16:48

Как бы то ни было, вам удалось найти решение. Отметьте свое решение как ответ, чтобы любой, кто страдает, как вы, быстро получил ответ. - :)

Sats 03.12.2018 16:52

Хорошо, мне просто нужно подождать 19 часов, пока это будет разрешено, спасибо за ваш вклад, это был хороший намек, поскольку я раньше не знал о ListBoxItem ;-)

t3chb0t 03.12.2018 16:54

Похоже, вам следует избавиться от всех привязок ширины и просто оставить поле вокруг StackPanel, например:

<StackPanel Margin = "10" >

--- ОБНОВЛЕНО -

Разочарование - правильное слово. Хорошо, вот решение.

(1) Замените StackPanel сеткой.

(2) В ListBox установите для ScrollViewer.HorizontalScrollBarVisibility значение «Disabled».

<ListBox ScrollViewer.HorizontalScrollBarVisibility = "Disabled">
        <Grid Margin = "10" >
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row = "0" Text = "Title" Style = "{StaticResource NameStyle}"  />
            <TextBlock Grid.Row = "1" TextWrapping = "Wrap" Text = "lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text lots of text " Style = "{StaticResource MessageStyle}" />
        </Grid>
    </ListBox>

Это должно помочь.

ммм ... Я удалил все привязки Width, и это определенно проклятый StackPanel, и когда он не привязан к ListBox, он слишком широкий, и перенос текста не работает, а когда он привязан, он всегда на несколько пикселей шире. Это так безумно и неприятно :-(

t3chb0t 02.12.2018 14:01

Наконец-то я понял! Я нашел аналогичный вопрос и адаптировал его отвечать для своих нужд:

<Grid >
    <ListBox ItemsSource = "{Binding Exceptions}" d:DataContext = "{Binding Source = {StaticResource DesignViewModel}}" Margin = "30" >
        <ListBox.ItemContainerStyle>
            <Style TargetType = "ListBoxItem">
                <Setter Property = "Width" Value = "{Binding (Grid.ActualWidth), RelativeSource = {RelativeSource FindAncestor, AncestorType = {x:Type Grid}}}" />
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text = "{Binding Name}" Style = "{StaticResource NameStyle}"  />
                    <TextBlock Text = "{Binding Message}" Style = "{StaticResource MessageStyle}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

Уловка заключалась в том, чтобы связать Width из ListBoxItem с родителем. Святая корова! Это было сложно. Теперь он также хорошо масштабируется при изменении размера окна.

Причина перекрытия связана с шаблоном по умолчанию для ListBoxItem, для которого Padding установлено значение «4,1» и BorderThickness равно «1» как для самого себя, так и для внутреннего объекта Border. Вы можете использовать такой инструмент, как WPF Snoop, чтобы увидеть это.

Решение заключается в привязке к ActualWidth следующего уровня контейнера, в данном случае ContentPresenter.

<ListBox ItemsSource = "{Binding DataItems}"
         ScrollViewer.HorizontalScrollBarVisibility = "Disabled"
         HorizontalContentAlignment = "Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Background = "Yellow"
                  Width = "{Binding RelativeSource = {RelativeSource FindAncestor, 
                                                  AncestorType = {x:Type ContentPresenter}}, 
                          Path=ActualWidth}">
                <Grid.RowDefinitions>
                    <RowDefinition Height = "Auto" />
                    <RowDefinition Height = "Auto" />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row = "0" Text = "{Binding Id}" />
                <TextBlock Grid.Row = "1" Text = "{Binding Description}" TextWrapping = "Wrap" />
        </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Обратите внимание на свойства, установленные для ListBox, которые предотвращают рост содержимого за пределы ширины ListBox и принудительное изменение размера содержимого по мере увеличения ширины ListBox.

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