64

ListBox DataTemplate在 WPF 中有一个。我希望一件物品紧贴左侧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>
4

8 回答 8

147

我还必须设置:

HorizontalContentAlignment="Stretch"

在包含ListBox.

于 2008-09-25T20:45:33.467 回答
25
<Grid.Width>
    <Binding Path="ActualWidth" 
             RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" />
</Grid.Width>
于 2011-01-15T10:40:34.147 回答
4

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

第 0 列:WrapPanel
第 1 列:无
第 2 列:ListBox

听起来你想要WrapPanel在左边缘,ListBox在右边缘,以及空间来占据中间剩下的东西。

最简单的方法实际上是使用 a DockPanel,而不是 a Grid

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

WrapPanel这应该在和之间留下空白空间ListBox

于 2008-09-25T20:15:52.323 回答
2

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

<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 >
于 2012-10-10T13:47:55.197 回答
1

默认情况下Grid应该占据整个宽度,ListBox因为它的默认值ItemsPanel是 a VirtualizingStackPanel。我假设你没有改变ListBox.ItemsPanel

也许如果你摆脱了中间ColumnDefinition(其他都是默认的"*"),并把HorizontalAlignment="Left"你的WrapPanel和电话号码HorizontalAlignment="Right"放在ListBox。您可能需要稍作修改ListBox才能使电话号码更加右对齐,例如为DataTemplate它们创建一个。

于 2008-09-25T20:13:45.870 回答
1

如果要使用 a Grid,则需要将ColumnDefinitions 更改为:

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

如果您不需要使用 a Grid,那么您可以使用 a 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"未定义的控件都将填充剩余空间。

于 2008-09-25T20:31:53.720 回答
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>

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

<Grid.Width>
    <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{StaticResource conDoubleLimiter}"  />
</Grid.Width>
于 2016-11-19T20:28:20.467 回答
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>
于 2017-06-22T22:03:28.387 回答