我怎么做WPF数据模板填补整个宽度的列表框?
-
02-07-2019 - |
题
我有一个 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>
解决方案
我还必须设置:
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>
这应该在 WrapPanel
和 ListBox
之间留下空白。
延伸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 >
的 Grid
应该通过默认占整个宽度 ListBox
因为默认的 ItemsPanel
对它是 VirtualizingStackPanel
.我假定你有 不 改变了 ListBox.ItemsPanel
.
也许,如果你摆脱中间 ColumnDefinition
(其他是默认的 "*"
),并且把 HorizontalAlignment="Left"
在您的 WrapPanel
和 HorizontalAlignment="Right"
在 ListBox
用电话号码。你可能已经改变, ListBox
一位得到电话号码甚至更多的权利,对准,例如创建一个 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
。未定义&quot; DockPanel.Dock&quot;
的任何控件都将填充剩余空间。
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>
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>