2008-09-25 10 views
55

У меня есть ListBoxDataTemplate в WPF. Я хочу, чтобы один предмет был плотным с левой стороны от ListBox, а другой предмет был плотным с правой стороны, но я не могу понять, как это сделать.Как создать шаблон данных WPF для заполнения всей ширины списка?

До сих пор у меня есть 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> 
+0

Можете ли вы разместить свой XAML, чтобы было ясно, что у вас есть до сих пор? – 2008-09-25 20:00:02

ответ

129

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

HorizontalContentAlignment="Stretch" 

на содержащий ListBox.

+5

Ta pal. Поработал в поисках помощи, и это было по первой ссылке. Nice one :) – 2009-03-20 23:20:50

+0

@ Eric Haskins У меня такая же проблема для элемента управления Pivot для Windows Phone (``) Но где я должен поместите этот код? Я пробовал некоторые, но я не мог понять это. – SynerCoder 2012-10-04 15:30:37

1

Grid должен по умолчанию занимают всю ширину ListBox, потому что по умолчанию ItemsPanel для него является VirtualizingStackPanel. Я предполагаю, что у вас есть не изменен ListBox.ItemsPanel.

Может быть, если вы избавились от среднего ColumnDefinition (остальные по умолчанию "*"), и положить HorizontalAlignment="Left" на вашем WrapPanel и HorizontalAlignment="Right" на ListBox для телефонных номеров. Возможно, вам придется немного изменить это значение ListBox, чтобы получить номера телефонов с более высоким выравниванием по правому краю, например, для них создать DataTemplate.

4

Хорошо, вот что у вас есть:

Колонка 0: WrapPanel
Колонка 1: Ничего
Колонка 2: ListBox

Это звучит, как вы хотите, WrapPanel на левом краю, ListBox по праву край и пространство, чтобы заняться тем, что осталось посередине.

Самый простой способ сделать это на самом деле использовать DockPanel, а не Grid.

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

Это должно оставить пустое пространство между WrapPanel и ListBox.

1

Если вы хотите использовать 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" заполнит оставшееся пространство.

+4

Это не делает таблицу данных заполнением ширины списка. – 2009-05-11 12:00:26

+2

Вам нужно использовать HorizontalContentAlignment = "Stretch" в списке, как указано ниже – cbeuker 2011-02-17 23:42:06

20
<Grid.Width> 
    <Binding Path="ActualWidth" 
      RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" /> 
</Grid.Width> 
2

Расширение ответ 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 > 
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> 

Затем с помощью преобразователя в направлении ширины связывания:

<Grid.Width> 
    <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{StaticResource conDoubleLimiter}" /> 
</Grid.Width> 
0

Метод в ответе Тэке заставляет горизонтальную полосу прокрутки. Это можно устранить, добавив конвертер, чтобы уменьшить ширину сетки по ширине элемента управления вертикальной полосы прокрутки.

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>