Question

J'ai un ListBox DataTemplate dans WPF. Je souhaite qu'un élément soit serré contre le côté gauche du ListBox et un autre élément soit serré contre le côté droit, mais je ne vois pas comment faire.

Jusqu'à présent, j'ai une grille à trois colonnes. Les colonnes gauche et droite ont un contenu et le centre est un espace réservé dont la largeur est définie sur "*". Où vais-je mal?

Voici le 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>
Était-ce utile?

La solution

J'ai également dû définir:

HorizontalContentAlignment="Stretch"

sur le ListBox contenant .

Autres conseils

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

Ok, voici ce que vous avez:

Colonne 0: WrapPanel
Colonne 1: rien
Colonne 2: ListBox

On dirait que vous voulez WrapPanel sur le bord gauche, ListBox sur le bord droit et un espace pour occuper ce qui reste au milieu.

Le moyen le plus simple de procéder consiste à utiliser un DockPanel et non une Grille .

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

Cela devrait laisser un espace vide entre WrapPanel et ListBox .

Étendre la réponse de Taeke en définissant le ScrollViewer.HorizontalScrollBarVisibility = "Caché & " pour un ListBox permet au contrôle enfant de prendre la largeur du parent sans afficher la barre de défilement. up.

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

La grille doit par défaut occuper toute la largeur de la ListBox car le ItemsPanel par défaut est un VirtualizingStackPanel . Je suppose que vous n'avez pas changé ListBox.ItemsPanel .

Peut-être si vous vous êtes débarrassé du ColumnDefinition du milieu (les autres sont par défaut "*"), et insérez HorizontalAlignment = "Gauche". / code> sur votre WrapPanel et HorizontalAlignment = "Droit" sur ListBox pour les numéros de téléphone. Vous devrez peut-être modifier légèrement ListBox pour que les numéros de téléphone soient encore plus alignés à droite, par exemple pour créer un DataTemplate pour eux.

Si vous souhaitez utiliser une grille , vous devez modifier votre ColumnDefinition pour qu'il soit:

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

Si vous n'avez pas besoin d'utiliser une grille , vous pouvez utiliser un 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>

Notez le TextBlock à la fin. Tout contrôle sans "DockPanel.Dock" défini remplira l’espace restant.

La réponse de Taeke fonctionne bien et, conformément à la réponse de vancutterromney, vous pouvez désactiver la barre de défilement horizontale pour vous débarrasser de l’incompatibilité de taille gênante. Toutefois, si vous souhaitez que le meilleur des deux mondes - supprime la barre de défilement lorsqu'elle n'est pas utilisée, mais l'active automatiquement lorsque la ListBox devient trop petite, vous pouvez utiliser le convertisseur suivant:

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

Ensuite, définissez-le en XAML en fonction des valeurs max / min souhaitées, ainsi qu’un décalage pour traiter cette incohérence gênante de taille de 2 pixels comme indiqué dans les autres réponses:

<ListBox.Resources>
    <con:DoubleLimiterConverter x:Key="conDoubleLimiter" Min="450" Offset="-2"/>
</ListBox.Resources>

Utilisez ensuite le convertisseur dans la liaison de largeur:

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

La méthode employée dans la réponse de Taeke impose une barre de défilement horizontale. Ce problème peut être résolu en ajoutant un convertisseur permettant de réduire la largeur de la grille par la largeur du contrôle de la barre de défilement verticale.

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

Ajoutez un espace de nom au nœud racine de votre XAML.

xmlns:converters="clr-namespace:Converters"

Et mettez à jour la largeur de la grille pour utiliser le convertisseur.

<Grid.Width>
    <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" Converter="{converters:ListBoxItemWidthConverter}"/>
</Grid.Width>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top