Silverlight 3: ListBox数据模板HorizontalAlignment

28

我有一个ListBox,它的ItemTemplate绑定到一个DataTemplate。我的问题是,我无法让模板中的元素拉伸到ListBox的整个宽度。

<ListBox x:Name="listPeople" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
    Margin="0,0,0,0" Background="{x:Null}" SelectionMode="Extended" Grid.Row="1" 
    ItemTemplate="{StaticResource PersonViewModel.BrowserDataTemplate}" 
    ItemsSource="{Binding Mode=OneWay, Path=SearchResults}" >
</ListBox>

<DataTemplate x:Key="PersonViewModel.BrowserDataTemplate">
   <ListBoxItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
     <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,5,5,5">
       <Border Opacity=".1" x:Name="itemBorder"  Background="#FF000000"   
         HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
         CornerRadius="5,5,5,5" MinWidth="100" Height="50"/>
      </Grid>
   </ListBoxItem>
</DataTemplate>

如您所见,我已在网格中添加了一个边框来指示模板的宽度。我的目标是看到这个边框扩展到列表框的全部宽度。目前,它的宽度由其内容或MinWidth决定,而MinWidth是目前使其可见的唯一因素。


我确定这之前已经出现过了,所以我应该知道答案,但是:Silverlight的ListBox是否有HorizontalContentAlignment属性?如果有的话,那就是你想要设置为“Stretch”的属性。 - Matt Hamilton
1
你需要在ListBoxItem上设置HorizontalContentAlignment属性为"Stretch",而不是在ListBox上设置。 - markti
6个回答

68

我花了一个小时来解决这个问题,非常非常令人沮丧。你不需要覆盖整个ListBoxItem的默认样式,我无法让它起作用。最后,我通过在我的ListBox.ItemContainerStyle部分简单地重写HorizontalContentAlignment属性来解决了这个问题,例如:

            <ListBox x:Name="ClassList" ItemsSource="{Binding LineClasses}"
                     ScrollViewer.VerticalScrollBarVisibility="Visible"
                     SelectionMode="Extended"
                     ScrollViewer.HorizontalScrollBarVisibility="Hidden" HorizontalContentAlignment="Stretch"
                     HorizontalAlignment="Stretch" Loaded="ClassList_Loaded"
                     VerticalAlignment="Stretch" Grid.Row="0">
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                    </Style>
                </ListBox.ItemContainerStyle>
                    <ListBox.ItemTemplate>

                    <DataTemplate>
                        <Border BorderBrush="Black" CornerRadius="3" Background="#FFE88D34"
                            BorderThickness="1" HorizontalAlignment="Stretch" >
                            <Grid Background="Transparent" HorizontalAlignment="Stretch" >
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <TextBlock 
                                    Grid.Column="0" HorizontalAlignment="Stretch"
                                    Margin="2"                                   
                                    FontSize="10"
                                    Text="{Binding DisplayClassNm}"/>
                            </Grid>

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

这对我非常有效。

Myles


这些代码行: <ListBox.ItemContainerStyle> ... </ListBox.ItemContainerStyle>对我来说很有效,干净简单... - Gabriel Mongeon
1
我并没有主张覆盖整个ListBoxItem的控件模板。在我的回答中,我给出了与您相同的指导:“在ListBox的ItemContainerStyle上设置HorizontalContentAlignment属性”。我只是提供了更多关于其工作原理的信息。 - markti
帮了我很多。有趣的是https://dev59.com/XnRA5IYBdhLWcg3wwwzD#2924249有更多的赞... - Jacek Gorgoń
非常好的答案,它也适用于ListView。这是唯一一个帮助我处理ListView内自定义控件的答案。 - Juan Pablo Gomez

29
创建 ListBox 的数据模板时,不应该包含 <ListBoxItem> 标签。数据模板的内容将放置在生成的容器中。您可以使用 ItemContainerStyle 控制如何构造该容器。
默认情况下,使用 ListBoxItem 控件样式来默认定义 ItemContainerStyle。此样式将 ListBoxItem.HorizontalContentAlignment 属性设置为“左侧”。请注意 ContentPresenter 将其 HorizontalAlignment 绑定到此属性。
当绑定到您的 ListBox 时,需要覆盖正在生成的 ListBoxItem 容器的样式。这可以通过设置 ItemContainerStyle 来完成。将 HorizontalContentAlignment 属性设置为"Stretch"。
下面是默认的 ListBoxItem 样式,供参考。
<Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
            <Setter Property="Padding" Value="3"/>
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Top"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="TabNavigation" Value="Local"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Grid Background="{TemplateBinding Background}">
                            <!-- VSM excluded for readability -->
                            <Rectangle x:Name="fillColor" Fill="#FFBADDE9" RadiusX="1" RadiusY="1" IsHitTestVisible="False" Opacity="0"/>
                            <Rectangle x:Name="fillColor2" Fill="#FFBADDE9" RadiusX="1" RadiusY="1" IsHitTestVisible="False" Opacity="0"/>
                            <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
                            <Rectangle x:Name="FocusVisualElement" Stroke="#FF6DBDD1" StrokeThickness="1" RadiusX="1" RadiusY="1" Visibility="Collapsed"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

1

这里是使用控件模板和数据模板来控制列表框的示例。请参考XAML标记,该标记可以为列表框项拉伸边框。


我也被告知尝试HorizontalContentAlignment="Stretch",但不幸的是它并没有帮助我解决问题。但幸运的是,上面提供的链接(搜索stretch),将xaml <ListBox.ItemContainerStyle>放入我的<ListBox>中确实像魔法一样奏效了!谢谢。 - PHenry

0

我的ListBoxItem包含一个CheckBox,上述解决方案对我没有起作用(很可能是由于CheckBox的性质而不是这些解决方案)。我能够通过不绑定到复选框的“Content”属性,而是显式定义XAML内联来强制执行此功能:

<CheckBox HorizontalAlignment="Stretch" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}">
    <TextBlock
        MinWidth="130"
        Margin="0,-2,0,0"
        HorizontalAlignment="Stretch"
        Text="{Binding Path=DisplayText}" />
</CheckBox>

需要边距是因为文本框的文本与复选框的勾选框不对齐。同时,最小宽度也是必要的。


0

我正在使用Silverlight 5和VS 2012进行工作。我遇到了同样的问题。我有一个水平的listbox,其中包含我的自定义对象作为ItemsSource。我希望listbox项可以展开。但它们没有展开。我不想为每个listbox项提供任何硬编码宽度。我尝试了这里的所有答案,但都没有起作用。我只是给出了ItemsSource ={Binding Persons} DisplayMemberPath="First Name"。就这些。


-1

我注意到了两件事情,因为我也遇到了同样的问题,而且无法像你尝试的那样解决它。

首先,您不需要在DataTemplate中显式放置ListBoxItem。这会自动为您创建,因此实际上您的ListBoxItem位于为您创建的ListBoxItem内部。我在Snoop中进行了确认。

其次,我不知道为什么,但我也无法从对齐属性中获得拉伸行为。我将其更改为使用RelativeSource绑定Width属性到包含ListBoxItem的ActualWidth属性。这对我有用。

Width="{Binding RelativeSource={RelativeSource 
   AncestorType={x:Type ListBoxItem}}, Path=ActualWidth}"

如果您需要在为您隐式创建的ListBoxItem上设置样式属性,请在ListBox.ItemContainerStyle元素内部使用Style元素。
希望这可以帮助到您...

我不相信RelativeSource在Silverlight中可用。 - Lee
你说得对,我没有考虑到那个。实际上在SL3中你可以执行元素对元素的绑定,所以只需将Grid的Width绑定到ListBox的ActualWidth即可。如果因为padding或其他原因出现了一点偏差,你可以使用IValueConverter来修复它。 - Rich
请问您是否有更多的示例代码呢?我正在使用WPF,我已经设置了一个带有Grid配置的DataTemplate的ListBox。我还为ListBox.ItemContainerStyle设置了一个模板,并将HorizontalContentAlignment设置为Stretch,但这并没有解决我的问题。我希望能够像您在上面的示例代码中所做的那样,使用RelativeBinding到ActualWidth。 - Luke
1
我尝试使用 <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=ActualWidth}"/> 在 ListBox.ItemContainerStyle 中设置宽度,但没有成功。 - Luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接