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

时间:2008-09-25 19:18:45

标签: wpf layout listbox datatemplate

我在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>

8 个答案:

答案 0 :(得分:135)

我还必须设置:

HorizontalContentAlignment="Stretch"

包含ListBox

答案 1 :(得分:23)

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

答案 2 :(得分:4)

好的,这就是你所拥有的:

第0栏:WrapPanel
第1栏:什么都没有 第2栏:ListBox

听起来你想要左边的WrapPanel,右边的ListBox,以及占据中间左边的空间。

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

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

这应该在WrapPanelListBox之间留出空白区域。

答案 3 :(得分:2)

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

<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 >

答案 4 :(得分:1)

Grid默认情况下会占用ListBox的整个宽度,因为默认ItemsPanelVirtualizingStackPanel。我假设您已更改ListBox.ItemsPanel

也许如果你摆脱了中间ColumnDefinition(其他人是默认"*"),并将HorizontalAlignment="Left"放在你的WrapPanelHorizontalAlignment="Right"ListBox表示电话号码。您可能需要稍微更改ListBox以使电话号码更加右对齐,例如为其创建DataTemplate

答案 5 :(得分:1)

如果您想使用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"的控件都将填充剩余空间。

答案 6 :(得分:0)

Taeke的答案很有效,根据vancutterromney的回答,您可以禁用水平滚动条以摆脱恼人的大小不匹配。但是,如果您确实想要两全其美 - 在不需要时删除滚动条,但在ListBox变得太小时自动启用滚动条,则可以使用以下转换器:

/// <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>

答案 7 :(得分:0)

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

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>