Wie fülle ich eine WPF-Datenvorlage aus, die die gesamte Breite der Listbox ausfüllt?


Answers

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

Ich habe eine ListBox DataTemplate in WPF. Ich möchte, dass ein Element dicht an der linken Seite der ListBox und ein anderes Objekt an der rechten Seite anliegt, aber ich kann nicht herausfinden, wie das geht.

Bisher habe ich ein Grid mit drei Spalten, die linke und die rechte haben einen Inhalt und die Mitte ist ein Platzhalter, dessen Breite auf "*" gesetzt ist. Wo gehe ich falsch?

Hier ist der 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>



Wenn Taeke die Antwort erweitert und ScrollViewer.HorizontalScrollBarVisibility="Hidden" für eine ListBox kann das ListBox Steuerelement die Breite des übergeordneten ListBox übernehmen und die Bildlaufleiste nicht ListBox werden.

<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 >



Die Methode in Taekes Antwort erzwingt eine horizontale Bildlaufleiste. Dies kann behoben werden, indem ein Konverter hinzugefügt wird, um die Breite des Rasters um die Breite der vertikalen Bildlaufleiste zu reduzieren.

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());
        }
    }
}

Fügen Sie dem Stammknoten Ihres XAML einen Namespace hinzu.

xmlns:converters="clr-namespace:Converters"

Und aktualisieren Sie die Grid-Breite, um den Konverter zu verwenden.

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



Wenn Sie ein Grid möchten, müssen Sie Ihre ColumnDefinition ändern:

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>

Wenn Sie kein Grid , können Sie ein 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>

Beachten Sie den TextBlock am Ende. Jedes Steuerelement, für das kein "DockPanel.Dock" definiert ist, füllt den verbleibenden Speicherplatz aus.