Удалите дополнительные вертикальные пробелы из WPF - PullRequest
2 голосов
/ 10 августа 2011
    <Border CornerRadius="2,2,2,2" BorderThickness="1" BorderBrush="LightSkyBlue" Margin="5,2,2,2" x:Name="PersonBorder" Visibility="Collapsed">
            <StackPanel Orientation="Vertical">

 <ListBox Name="personListBoxTest" 
          BorderThickness="0"
          ScrollViewer.HorizontalScrollBarVisibility="Hidden"
          ScrollViewer.VerticalScrollBarVisibility="Auto"
          HorizontalContentAlignment="Stretch"
          Background="LemonChiffon"
          >
    <ListBox.ItemTemplate >
        <DataTemplate>
            <StackPanel>
                <StackPanel Orientation="Horizontal" Background="Pink">
                    <StackPanel Orientation="Horizontal" Visibility="{Binding ElementName=Involvement, Path=Text, Converter={StaticResource cIsVisibleOrCollapsed}}" Margin="0,0,5,0">
                        <TextBlock Text="Involvement:"/>
                        <TextBlock Margin="5,0,0,0" Text="{Binding Path=NameInvolvementType}" Foreground="Blue" x:Name="Involvement"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock  Text="Name:"/>
                        <TextBlock Margin="3,0,0,0" Text="{Binding Path=FirstName}" Foreground="Blue" />
                        <TextBlock Margin="3,0,0,0" Text="{Binding Path=MiddleName}" Foreground="Blue" />
                        <TextBlock Margin="3,0,0,0" Text="{Binding Path=LastName}" Foreground="Blue" />
                        <TextBlock Margin="3,0,0,0" Text="{Binding Path=NameSuffix}" Foreground="Blue" />
                        <TextBlock Margin="5,0,0,0" Text="DOB:"/>
                        <TextBlock Margin="3,0,0,0" Text="{Binding Path=BirthDate, StringFormat=MM/dd/yyyy}" Foreground="Blue" />
                    </StackPanel>
                </StackPanel>
                <StackPanel  Visibility="{Binding ElementName=myEventAddress,Path=Visibility, Converter={StaticResource cVisibilityMirror}}" Orientation="Horizontal" >
                    <TextBlock Text="Address:" />
                    <EventDet:EventAddress Margin="5,0,0,0" x:Name="myEventAddress" Foreground="Blue" CityTextBlockOrientation="Horizontal" />
                </StackPanel>

                <StackPanel Visibility="{Binding ElementName=Phone1, Path=Text, Converter={StaticResource cIsVisibleOrCollapsed}}" Orientation="Horizontal">
                    <TextBlock Text="Home:" />
                    <TextBlock Margin="5,0,0,0" Text="{Binding Path=Phone1}" Foreground="Blue" x:Name="Phone1"/>
                </StackPanel>
                <StackPanel Visibility="{Binding ElementName=Phone2, Path=Text, Converter={StaticResource cIsVisibleOrCollapsed}}" Orientation="Horizontal">
                    <TextBlock Text="Mobile:" />
                    <TextBlock Margin="5,0,0,0" Text="{Binding Path=Phone2}" Foreground="Blue" x:Name="Phone2"/>
                </StackPanel>
                <StackPanel Visibility="{Binding ElementName=Phone3, Path=Text, Converter={StaticResource cIsVisibleOrCollapsed}}" Orientation="Horizontal">
                    <TextBlock Text="Work:" />
                    <TextBlock Margin="5,0,0,0" Text="{Binding Path=Phone3}" Foreground="Blue" x:Name="Phone3"/>
                </StackPanel>


                <StackPanel x:Name="PersonAlertSP" Visibility="Collapsed" Background="WhiteSmoke">
                    <TextBlock Text="Alerts:" />
                    <ListBox ItemsSource="{Binding Path=PersonAlertList}" x:Name="PersonAlertListBox"  BorderThickness="1" >
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Path=AlertType}" Margin="0,0,5,0" Foreground="Blue" Width="150"/>
                                    <TextBlock Text="{Binding Path=Description}" Margin="0,0,5,0" Foreground="Blue"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>


            </StackPanel>

        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

</StackPanel>
</Border>

код позади:

//this is a little unweidly, but its test code until this works
MobileWPF.singleton.EventDetailsTabControl.myEventDetailControl.personListBoxTest.ItemsSource =
    dc.SessionEvent.SessionPersons.ToList();

Вот изображение результата с 6 пунктами, все данные - бессмысленные данные теста:

screenshot

РЕДАКТИРОВАТЬ 2:

Немного поиграв с этим, я думаю, это то, что происходит ... Сначала ListBox является жадным и занимает максимальное количество вертикального пространства, затем выполняются некоторые вычисления IValueConverter, а некоторые элементы сворачиваются. Однако, как только это будет сделано, высота ListBox не обновляется.

РЕДАКТИРОВАТЬ 3:

Я попытался преобразовать PersonListBoxTest в ItemsControl, а не в ListBox, с единственной разницей в коде и объявлением <ItemsControl.ItemTemplate > ... И теперь все работает как положено, без лишних пробелов.

Так что каким-то образом ItemsControl учитывает тот факт, что некоторые из моих элементов свернуты через IValueConverters, а ListBox нет. Я поиграл с атрибутом VirtualizingStackPanel в ListBox, установив для IsVirtualizing значения true и false (без изменений) перед тестированием ItemsControl.

Я дам очки всем, кто может объяснить, почему это работает, как я это наблюдал.
Спасибо всем за ваши ответы, вы никогда не знаете, что будет иметь значение.

Вот пример используемого IValueConverter, все они примерно одинаковы.

[ValueConversion(typeof(object), typeof(System.Windows.Visibility))]
public class NullToVisibleOrCollapsed : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null) return System.Windows.Visibility.Collapsed;

        if (value is Image)
        {
            if (((Image)value).Source == null) return System.Windows.Visibility.Collapsed;
            return System.Windows.Visibility.Visible;
        }

        if (value is string)
        {
            string myString = (string)value;
            if (string.IsNullOrEmpty(myString) == true)
                return System.Windows.Visibility.Collapsed;
        }

        if (value is int)
        {
            int myInt = (int)value;
            if (myInt == 0)
                return System.Windows.Visibility.Collapsed;
        }

        return System.Windows.Visibility.Visible;
    }

Ответы [ 6 ]

2 голосов
/ 30 августа 2011

Причина, по которой это происходит, заключается в том, что ListBox переопределяет настройки ItemsPanelTemplate по умолчанию для использования VirtualizingStackPanel.Это происходит потому, что VirtualizingStackPanel поддерживает виртуализацию пользовательского интерфейса, что означает, что только видимые элементы управления оцениваются и создаются, что может повысить производительность больших наборов данных.

Во время виртуализации пользовательского интерфейса элемент управления проверяет видимость дочернего элемента,затем измеряет его и его потомков.Этот порядок оценки является основной причиной, по которой вы видите дополнительное пространство.Вы используете связанное значение дочернего элемента, чтобы установить видимость вашего родительского элемента.

<StackPanel 
    ...
    Visibility="{Binding 
                    ElementName=Phone1,
                    Path=Text,
                    Converter={StaticResource cIsVisibleOrCollapsed}}">
    <TextBlock
        x:Name="Phone1"
        Text="{Binding Path=Phone1}" />
</StackPanel>

Когда платформа оценивает ваш StackPanel, видимость еще не установлена, поэтому по умолчанию она становится видимой.Это можно исправить, если вы изменили привязку Visibility, чтобы вместо нее использовать тот же путь привязки, что и у дочернего свойства.

<StackPanel 
    ...
    Visibility="{Binding Phone1, 
                    Converter={StaticResource cIsVisibleOrCollapsed}}">
    <TextBlock
        x:Name="Phone1"
        Text="{Binding Path=Phone1}" />
</StackPanel>

Вы также можете указать FallbackValue из Collapsed, что говорит движку использоватьVisibility.Collased в случае, если он не может разрешить привязку.Тем не менее, я буду осторожен с этим, потому что кажется, что это испортит измерения пользовательского интерфейса, что может привести к другим нежелательным эффектам.

Наконец, обычный шаблон ItemsControl не нужно предварительно измерять, потому чтоон не поддерживает виртуализацию пользовательского интерфейса.Другими словами, элементы управления создаются, а затем скрываются, и размер корректируется соответствующим образом.

1 голос
/ 26 августа 2011

По умолчанию элементы управления будут расширяться, чтобы заполнить все пространство, которое предоставит его контейнер.Это то, что вы видите, и это ожидаемо, так как вы не сказали ему делать что-либо еще (то есть вы не установили никаких свойств выравнивания в ListBox).

Если вы предпочитаетеListBox занимает только столько высоты, сколько необходимо для отображения его элементов, а затем устанавливает для свойства VerticalAlignment значение, отличное от значения по умолчанию Stretch.Например:

<ListBox Name="personListBoxTest" 
         VerticalAlignment="Top"
         ...

Или вы можете использовать Bottom или Center, если хотите, - все, что наиболее подходит для вашего макета.

Предполагается, что вы используете Top,тогда, если в списке только достаточно элементов, чтобы заполнить половину пространства, указанного родительским объектом ListBox, весь ListBox займет только столько места, а оставшаяся часть родительского элемента будет пустой.Но если будет так много элементов ListBox (или родитель станет настолько маленьким), что элементы не будут умещаться не все, ListBox заполнит все пространство и покажет полосу прокрутки, как вы этого хотите.

0 голосов
/ 01 сентября 2011

Вам необходимо сделать так, чтобы контейнер, содержащий ListBox, имел высоту AUTO

ListBox1 находится в строке высоты AUTO

ListBox2 находится в диапазоне строк высоты *

Это позволит вам иметь правильную высоту в списке в качестве размера значений в контейнере вплоть до максимальной высоты контейнера, в котором он находится ... это немного запутанно, но надеюсь, что это имеет смысл.

Надеюсь, это поможет!

См. Этот пример кода

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <ListBox Grid.Column="0" Grid.Row="0" Background="blue">
        <ListBoxItem>I'm an item in listbox1</ListBoxItem>
        <ListBoxItem>I'm an item in listbox1</ListBoxItem>
        <ListBoxItem>I'm an item in listbox1</ListBoxItem>
        <ListBoxItem>I'm an item in listbox1</ListBoxItem>
        <ListBoxItem>I'm an item in listbox1</ListBoxItem>
        <ListBoxItem>I'm an item in listbox1</ListBoxItem>
    </ListBox>

    <ListBox Grid.Column="1" Grid.RowSpan="2" Grid.Row="0"  Background="red">
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
        <ListBoxItem>I'm an item in listbox2</ListBoxItem>
    </ListBox>
</Grid>

0 голосов
/ 01 сентября 2011

Возможно ...

<StackPanel LastChildFill="False">
0 голосов
/ 30 августа 2011

Если я правильно понимаю ваш вопрос, вы можете использовать Height="Auto" для своего списка (или других элементов управления), и если вы хотите, чтобы высота вашего окна обновлялась в соответствии со списком, вы можете привязать высоту вашего окна к списку с помощью ниже код:

Height="{Binding ActualHeight, ElementName=personListBoxTest}"

Я надеюсь, что это может быть полезно для вас.

0 голосов
/ 10 августа 2011

Оберните ваш ListBox в Grid и установите его VerticalAlignment="Top"

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

<Grid>
    <ListBox VerticalAlignment="Top" ... />
</Grid>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...