如何使 WPF 数据模板填充列表框的整个宽度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/135375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I make a WPF data template fill the entire width of the listbox?
提问by Eric Haskins
I have a ListBox
DataTemplate
in WPF. I want one item to be tight against the left side of the ListBox
and another item to be tight against the right side, but I can't figure out how to do this.
我ListBox
DataTemplate
在 WPF 中有一个。我希望一件物品紧贴左侧ListBox
,另一件紧贴右侧,但我不知道如何做到这一点。
So far I have a Grid
with three columns, the left and right ones have content and the center is a placeholder with it's width set to "*". Where am I going wrong?
到目前为止,我有一个Grid
三列,左右两列有内容,中心是一个占位符,其宽度设置为“*”。我哪里错了?
Here is the code:
这是代码:
<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>
回答by Eric Haskins
I also had to set:
我还必须设置:
HorizontalContentAlignment="Stretch"
on the containing ListBox
.
在包含ListBox
.
回答by Taeke
<Grid.Width>
<Binding Path="ActualWidth"
RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" />
</Grid.Width>
回答by 17 of 26
Ok, here's what you have:
好的,这是你所拥有的:
Column 0: WrapPanel
Column 1: Nothing
Column 2: ListBox
第 0 列:WrapPanel
第 1 列:无
第 2 列:ListBox
It sounds like you want WrapPanel
on the left edge, ListBox
on the right edge, and space to take up what's left in the middle.
听起来你想要WrapPanel
在左边缘、ListBox
右边缘和空间来占据中间剩下的东西。
Easiest way to do this is actually to use a DockPanel
, not a Grid
.
最简单的方法实际上是使用 a DockPanel
,而不是 a Grid
。
<DockPanel>
<WrapPanel DockPanel.Dock="Left"></WrapPanel>
<ListBox DockPanel.Dock="Right"></ListBox>
</DockPanel>
This should leave empty space between the WrapPanel
and the ListBox
.
这应该在WrapPanel
和之间留下空白空间ListBox
。
回答by vancutterromney
Extending Taeke's answer, setting the ScrollViewer.HorizontalScrollBarVisibility="Hidden"
for a ListBox
allows the child control to take the parent's width and not have the scroll bar show up.
扩展 Taeke 的答案,设置ScrollViewer.HorizontalScrollBarVisibility="Hidden"
for 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 >
回答by Phobis
If you want to use a Grid
, then you need to change your ColumnDefinition
s to be:
如果要使用 a Grid
,则需要将ColumnDefinition
s更改为:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
If you don't need to use a Grid
, then you could use a DockPanel
:
如果您不需要使用 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>
Notice the TextBlock
at the end. Any control with no "DockPanel.Dock"
defined will fill the remaining space.
注意TextBlock
最后。任何"DockPanel.Dock"
未定义的控件将填充剩余空间。
回答by Joel B Fant
The Grid
should by default take up the whole width of the ListBox
because the default ItemsPanel
for it is a VirtualizingStackPanel
. I'm assuming that you have notchanged ListBox.ItemsPanel
.
在Grid
默认情况下应承担的整个宽度ListBox
,因为默认ItemsPanel
它是一个VirtualizingStackPanel
。我假设你没有改变ListBox.ItemsPanel
。
Perhaps if you got rid of the middle ColumnDefinition
(the others are default "*"
), and put HorizontalAlignment="Left"
on your WrapPanel
and HorizontalAlignment="Right"
on the ListBox
for phone numbers. You may have to alter that ListBox
a bit to get the phone numbers even more right-aligned, such as creating a DataTemplate
for them.
也许如果你去掉中间的ColumnDefinition
(其他是默认的"*"
),并把HorizontalAlignment="Left"
你的WrapPanel
和HorizontalAlignment="Right"
放在ListBox
电话号码上。您可能需要ListBox
稍微更改一下以使电话号码更加右对齐,例如DataTemplate
为它们创建一个。
回答by BCA
Taeke's answer works well, and as per vancutterromney's answer you can disable the horizontal scrollbar to get rid of the annoying size mismatch. However, if you do want the best of both worlds--to remove the scrollbar when it is not needed, but have it automatically enabled when the ListBox becomes too small, you can use the following converter:
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();
}
}
Then define it in XAML according to the desired max/min values, as well an offset to deal with that annoying 2-pixel size mismatch as mentioned in the other answers:
然后根据所需的最大/最小值在 XAML 中定义它,以及处理其他答案中提到的令人讨厌的 2 像素大小不匹配的偏移量:
<ListBox.Resources>
<con:DoubleLimiterConverter x:Key="conDoubleLimiter" Min="450" Offset="-2"/>
</ListBox.Resources>
Then use the converter in the Width binding:
然后在 Width 绑定中使用转换器:
<Grid.Width>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{StaticResource conDoubleLimiter}" />
</Grid.Width>
回答by Kevin Hilt
The method in Taeke's answer forces a horizontal scroll bar. This can be fixed by adding a converter to reduce the grid's width by the width of the vertical scrollbar control.
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());
}
}
}
Add a namespace to the root node of your XAML.
将命名空间添加到 XAML 的根节点。
xmlns:converters="clr-namespace:Converters"
And update the Grid width to use the converter.
并更新网格宽度以使用转换器。
<Grid.Width>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{converters:ListBoxItemWidthConverter}"/>
</Grid.Width>