web-dev-qa-db-ja.com

WPFitemscontrolの最後のアイテムに異なるテンプレートを使用する

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>

私の問題の解決策を与えることができる人はいますか?ありがとうございました!

20
Bram W.

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>
54
Bram W.

DataTemplateSelector を使用できます。 SelectTemplate() メソッドでは、アイテムが最後かどうかを確認してから、他のテンプレートを返すことができます。

XAMLの場合:

<ItemsControl.ItemTemplate>     
  <DataTemplate>
      <ContentPresenter 
             ContentTemplateSelector = "{StaticResource MyTemplateSelector}">

背後にあるコード:

 private sealed class MyTemplateSelector: DataTemplateSelector
 { 

    public override DataTemplate SelectTemplate(
                                      object item, 
                                      DependencyObject container)
    {
        // ...
    }
  }
7
sll

このソリューションは最後の行に影響し、基になるコレクションへの変更で更新されます。


CodeBehind

コンバーターが正しく機能するには、現在のアイテム、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();
        }
    }

XAML

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

SnapShot

そして、実際のスナップショット

enter image description here コードはこの 'codeproject'からitemscontrolに追加されました https://www.codeproject.com/Articles/242628/A-Simple-Cross-Button-for-WPF

最後のアイテムのテキストが赤で表示されていることに注意してください

3
Declan Taylor

1つの質問...ItemsControlと言うのではなくListBoxを使用していて、文字列のコレクションにバインドされているように見えます。個々の部分をフォーマットせずに結果のテキストを表示します。これにより、目的の出力が実際のItemsControl自体ではなく、質問で述べた文字列自体であるかどうか疑問に思います。

私がそれについて正しければ、itemsコレクションにバインドされた単純なTextBlockを使用することを検討しましたが、コンバーターを介して供給されますか?次に、コンバーター内で、valueを文字列の配列にキャストし、次にConvertメソッドで、カンマを区切り文字として使用してJoinするだけで、自動的にのみそのように、要素の間にそれらを追加します...

var strings = (IEnumerable<String>)value;

return String.Join(", ", strings);
0
Mark A. Donohoe