Itemscontrolでカスタムテンプレートを使用して、次の結果を表示しています。
item 1, item 2, item3,
最後のアイテムのテンプレートを変更して、結果が次のようになるようにします。
item 1, item2, item3
ItemsControl:
<ItemsControl ItemsSource="{Binding Path=MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text=", "/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
私の問題の解決策を与えることができる人はいますか?ありがとうございました!
XAMLのみを使用して問題の解決策を見つけました。同じことをする必要がある人がいる場合は、これを使用してください:
<ItemsControl ItemsSource="{Binding Path=MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="comma" Text=", "/>
<TextBlock Text="{Binding}"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter TargetName="comma" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
DataTemplateSelector を使用できます。 SelectTemplate() メソッドでは、アイテムが最後かどうかを確認してから、他のテンプレートを返すことができます。
XAMLの場合:
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentPresenter
ContentTemplateSelector = "{StaticResource MyTemplateSelector}">
背後にあるコード:
private sealed class MyTemplateSelector: DataTemplateSelector
{
public override DataTemplate SelectTemplate(
object item,
DependencyObject container)
{
// ...
}
}
このソリューションは最後の行に影響し、基になるコレクションへの変更で更新されます。
コンバーターが正しく機能するには、現在のアイテム、itemscontrol、itemscountの3つのパラメーターが必要であり、現在のアイテムが最後のアイテムでもある場合はtrueを返します。
class LastItemConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
int count = (int)values[2];
if (values != null && values.Length == 3 && count>0)
{
System.Windows.Controls.ItemsControl itemsControl = values[0] as System.Windows.Controls.ItemsControl;
var itemContext = (values[1] as System.Windows.Controls.ContentPresenter).DataContext;
var lastItem = itemsControl.Items[count-1];
return Equals(lastItem, itemContext);
}
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
'PART_TextBox'という名前のテキストボックスを含むDataTemplateのデータトリガー:
<DataTemplate.Triggers>
<DataTrigger Value="True" >
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource LastItemConverter}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" />
<Binding RelativeSource="{RelativeSource Self}"/>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" Path="Items.Count"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" TargetName="PART_TextBox" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
Xamlの静的リソースとしてのコンバーター
<Window.Resources>
<local:LastItemConverter x:Key="LastItemConverter" />
</Window.Resources>
そして、実際のスナップショット
コードはこの 'codeproject'からitemscontrolに追加されました https://www.codeproject.com/Articles/242628/A-Simple-Cross-Button-for-WPF
最後のアイテムのテキストが赤で表示されていることに注意してください
1つの質問...ItemsControl
と言うのではなくListBox
を使用していて、文字列のコレクションにバインドされているように見えます。個々の部分をフォーマットせずに結果のテキストを表示します。これにより、目的の出力が実際のItemsControl
自体ではなく、質問で述べた文字列自体であるかどうか疑問に思います。
私がそれについて正しければ、itemsコレクションにバインドされた単純なTextBlock
を使用することを検討しましたが、コンバーターを介して供給されますか?次に、コンバーター内で、value
を文字列の配列にキャストし、次にConvert
メソッドで、カンマを区切り文字として使用してJoin
するだけで、自動的にのみそのように、要素の間にそれらを追加します...
var strings = (IEnumerable<String>)value;
return String.Join(", ", strings);