WPFにListBox
DataTemplate
があります。 1つのアイテムをListBox
の左側に密着させ、別のアイテムを右側に密着させたいのですが、これを行う方法がわかりません。
これまでのところ、3つの列を持つ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>
私も設定する必要がありました:
HorizontalContentAlignment="Stretch"
含むListBox
。
<Grid.Width>
<Binding Path="ActualWidth"
RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" />
</Grid.Width>
OK、これがあなたの持っているものです:
列0:WrapPanel
列1:何もない
列2:ListBox
左端にWrapPanel
、右端にListBox
、および中央に残っているものを占めるスペースが必要なようです。
これを行う最も簡単な方法は、実際にはDockPanel
ではなくGrid
を使用することです。
<DockPanel>
<WrapPanel DockPanel.Dock="Left"></WrapPanel>
<ListBox DockPanel.Dock="Right"></ListBox>
</DockPanel>
これにより、WrapPanel
とListBox
の間に空白が残るはずです。
Taekeの答えを拡張し、ListBox
にScrollViewer.HorizontalScrollBarVisibility="Hidden"
を設定すると、子コントロールが親の幅を取り、スクロールバーが表示されなくなります。
<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 >
デフォルトのGrid
はListBox
であるため、ItemsPanel
はデフォルトでVirtualizingStackPanel
の幅全体を使用する必要があります。 _ListBox.ItemsPanel
_が変更されたnotがあると仮定しています。
おそらく、中間のColumnDefinition
(他はデフォルトの_"*"
_)を取り除いて、WrapPanel
に_HorizontalAlignment="Left"
_を、電話番号のListBox
に_HorizontalAlignment="Right"
_を置いた場合。電話番号をさらに右揃えにするために、ListBox
を少し変更する必要がある場合があります(たとえば、DataTemplate
を作成するなど)。
Grid
を使用する場合は、ColumnDefinition
sを次のように変更する必要があります。
<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の答えのメソッドは、水平スクロールバーを強制します。これは、コンバーターを追加して、グリッドの幅を垂直スクロールバーコントロールの幅だけ減らすことで修正できます。
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>
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();
}
}
次に、他の回答に記載されているように、目的の最大/最小値、およびその厄介な2ピクセルサイズの不一致に対処するためのオフセットに従って、XAMLで定義します。
<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>