Использовать другой шаблон для последнего элемента в элементе управления WPF - PullRequest
18 голосов
/ 14 октября 2011

Я использую собственный шаблон в моем 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>

Кто-нибудь может дать решение для моей проблемы?Спасибо!

Ответы [ 4 ]

53 голосов
/ 17 октября 2011

Я нашел решение для моей проблемы, используя только 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>
7 голосов
/ 14 октября 2011

Вы можете использовать DataTemplateSelector , в методе SelectTemplate () вы можете проверить, является ли элемент последним, а затем вернуть другой шаблон.

В XAML:

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

В коде:

 private sealed class MyTemplateSelector: DataTemplateSelector
 { 

    public override DataTemplate SelectTemplate(
                                      object item, 
                                      DependencyObject container)
    {
        // ...
    }
  }
3 голосов
/ 28 августа 2017

Это решение влияет на последнюю строку и обновляется с изменениями базовой коллекции:


CodeBehind

Конвертеру для правильной работы требуются 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();
        }
    }

1010 * XAML * Триггер данных для шаблона данных, который содержит текстовое поле с именем 'PART_TextBox': <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> 1019 * SnapShot * И снимок этого в действии enter image description here Код был добавлен в элемент управления из этого 'codeproject' https://www.codeproject.com/Articles/242628/A-Simple-Cross-Button-for-WPF Отметьте текст последнего элемента красным

0 голосов
/ 04 марта 2017

Один вопрос ... Я вижу, вы используете ItemsControl, а не ListBox, и что он, кажется, связан с набором строк, и что вы только пытаетесь отобразить полученный результат текст без форматирования отдельных частей, что заставляет меня задаться вопросом, является ли желаемый результат на самом деле самой строкой, как указано в вопросе, а не фактической ItemsControl как таковой.

Если я прав, вы рассматривали вопрос об использовании простого TextBlock, связанного с коллекцией предметов, но через конвертер? Затем внутри конвертера вы должны привести value к массиву строк, а затем в методе Convert просто Join, используя запятую в качестве разделителя, который будет автоматически добавлять их только между элементами, например, так ... .

var strings = (IEnumerable<String>)value;

return String.Join(", ", strings);
...