如何使WPF数据模板填充列表框的整个宽度?

我在WPF中有一个ListBox DataTemplate 。 我想要一个项目在左侧的ListBox和另一个项目紧靠在右侧,但我不知道如何做到这一点。

到目前为止,我有一个三列的Grid ,左侧和右侧的内容和中心是宽度设置为“*”的占位符。 我哪里错了?

这里是代码:

 <DataTemplate x:Key="SmallCustomerListItem"> <Grid HorizontalAlignment="Stretch"> <Grid.RowDefinitions> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="*"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <WrapPanel HorizontalAlignment="Stretch" Margin="0"> <!--Some content here--> <TextBlock Text="{Binding Path=LastName}" TextWrapping="Wrap" FontSize="24"/> <TextBlock Text=", " TextWrapping="Wrap" FontSize="24"/> <TextBlock Text="{Binding Path=FirstName}" TextWrapping="Wrap" FontSize="24"/> </WrapPanel> <ListBox ItemsSource="{Binding Path=PhoneNumbers}" Grid.Column="2" d:DesignWidth="100" d:DesignHeight="50" Margin="8,0" Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False" HorizontalAlignment="Stretch"/> </Grid> </DataTemplate> 

我还必须设置:

 HorizontalContentAlignment="Stretch" 

在包含的ListBox

 <Grid.Width> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" /> </Grid.Width> 

好的,这是你有什么:

列0: WrapPanel
专栏1:没有
第2列: ListBox

这听起来像你想要左边的WrapPanel ,右边的ListBox ,还有空间去占据左边的东西。

最简单的方法是使用DockPanel ,而不是Grid

 <DockPanel> <WrapPanel DockPanel.Dock="Left"></WrapPanel> <ListBox DockPanel.Dock="Right"></ListBox> </DockPanel> 

这应该留下WrapPanelListBox之间的空白空间。

扩展Taeke的答案,为ListBox设置ScrollViewer.HorizontalScrollBarVisibility="Hidden"允许子控件获取父宽度,而不显示滚动条。

 <ListBox Width="100" ScrollViewer.HorizontalScrollBarVisibility="Hidden"> <Label Content="{Binding Path=., Mode=OneWay}" HorizontalContentAlignment="Stretch" Height="30" Margin="-4,0,0,0" BorderThickness="0.5" BorderBrush="Black" FontFamily="Calibri" > <Label.Width> <Binding Path="Width" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}" /> </Label.Width> </Label> </ListBox > 

Grid默认占用ListBox的整个宽度,因为它的默认ItemsPanel是一个VirtualizingStackPanel 。 我假设你没有改变ListBox.ItemsPanel

也许如果你摆脱了中间ColumnDefinition (其他人是默认的"*" ),并将HorizontalAlignment="Left" ColumnDefinition HorizontalAlignment="Left"您的WrapPanelHorizontalAlignment="Right" ListBox的电话号码。 您可能需要稍微改变一下ListBox以使电话号码更加右alignment,比如为它们创build一个DataTemplate

如果你想使用一个Grid ,那么你需要改变你的ColumnDefinition为:

  <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> 

如果你不需要使用Grid ,那么你可以使用DockPanel

  <DockPanel> <WrapPanel DockPanel.Dock="Left"> <!--Some content here--> <TextBlock Text="{Binding Path=LastName}" TextWrapping="Wrap" FontSize="24"/> <TextBlock Text=", " TextWrapping="Wrap" FontSize="24"/> <TextBlock Text="{Binding Path=FirstName}" TextWrapping="Wrap" FontSize="24"/> </WrapPanel> <ListBox DockPanel.Dock="Right" ItemsSource="{Binding Path=PhoneNumbers}" Margin="8,0" Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/> <TextBlock /> </DockPanel> 

最后注意TextBlock 。 没有定义"DockPanel.Dock"任何控件将填充剩余的空间。

泰克的答案效果很好,根据vancutterromney的回答,您可以禁用水平滚动条来摆脱烦人的尺寸不匹配。 但是,如果您确实需要两全其美的解决scheme – 在不需要滚动条的情况下移除滚动条,但在列表框变得太小时自动启用该滚动条,则可以使用以下转换器:

 /// <summary> /// Value converter that adjusts the value of a double according to min and max limiting values, as well as an offset. These values are set by object configuration, handled in XAML resource definition. /// </summary> [ValueConversion(typeof(double), typeof(double))] public sealed class DoubleLimiterConverter : IValueConverter { /// <summary> /// Minimum value, if set. If not set, there is no minimum limit. /// </summary> public double? Min { get; set; } /// <summary> /// Maximum value, if set. If not set, there is no minimum limit. /// </summary> public double? Max { get; set; } /// <summary> /// Offset value to be applied after the limiting is done. /// </summary> public double Offset { get; set; } public static double _defaultFailureValue = 0; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || !(value is double)) return _defaultFailureValue; double dValue = (double)value; double minimum = Min.HasValue ? Min.Value : double.NegativeInfinity; double maximum = Max.HasValue ? Max.Value : double.PositiveInfinity; double retVal = dValue.LimitToRange(minimum, maximum) + Offset; return retVal; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

然后根据所需的最大/最小值在XAML中定义它,以及处理如其他答案中提到的令人讨厌的2像素大小不匹配的偏移量:

 <ListBox.Resources> <con:DoubleLimiterConverter x:Key="conDoubleLimiter" Min="450" Offset="-2"/> </ListBox.Resources> 

然后在宽度绑定中使用转换器:

 <Grid.Width> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{StaticResource conDoubleLimiter}" /> </Grid.Width> 

Taeke答案中的方法强制水平滚动条。 这可以通过添加一个转换器来减less垂直滚动条控件的宽度来减小网格的宽度。

 using System; using System.Globalization; using System.Windows; using System.Windows.Data; using System.Windows.Markup; namespace Converters { public class ListBoxItemWidthConverter : MarkupExtension, IValueConverter { private static ListBoxItemWidthConverter _instance; #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return System.Convert.ToInt32(value) - SystemParameters.VerticalScrollBarWidth; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } #endregion public override object ProvideValue(IServiceProvider serviceProvider) { return _instance ?? (_instance = new ListBoxItemWidthConverter()); } } } 

将命名空间添加到XAML的根节点。

 xmlns:converters="clr-namespace:Converters" 

并更新网格宽度以使用转换器。

 <Grid.Width> <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{converters:ListBoxItemWidthConverter}"/> </Grid.Width>