Как сделать так, чтобы шаблон данных WPF заполнял всю ширину списка?
у меня есть ListBoxDataTemplate в 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>
8 ответов:
<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.
расширение ответа Тхэке, установка
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 >
The
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в конце. Любой контроль без"DockPanel.Dock"определено заполнит оставшееся пространство.
ответ Taeke работает хорошо, и в соответствии с ответом vancutterromney вы можете отключить горизонтальную полосу прокрутки, чтобы избавиться от раздражающего несоответствия размера. Однако, если вы хотите лучшее из обоих миров-чтобы удалить полосу прокрутки, когда она не нужна, но она автоматически включается, когда список становится слишком маленьким, вы можете использовать следующий конвертер:
/// <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 в соответствии с желаемыми значениями max / min, а также смещение, чтобы справиться с этим раздражающим 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>
метод в ответе Тхэке заставляет горизонтальную полосу прокрутки. Это можно исправить, добавив конвертер для уменьшения ширины сетки на ширину элемента управления вертикальной полосой прокрутки.
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>
Comments