Как сделать так, чтобы шаблон данных 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>
801   8  

8 ответов:

Я также должен был установить:

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.

расширение ответа Тхэке, установка 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

    Ничего не найдено.