Home:ALL Converter>ItemsControl wrapping issue

ItemsControl wrapping issue

Ask Time:2019-03-31T22:04:17         Author:Sergey Alikin

Json Formatter

I did small custom ItemsControl to show some list as row of items. And it works almost perfectly.

<ItemsControl.ItemTemplate>
    <DataTemplate>
       <WrapPanel Orientation="Horizontal">
           <TextBlock x:Name="delimiter" Text=";" Margin="0 0 5 0"/>
           <TextBlock Text="{Binding LinkId}" />
       </WrapPanel>
       <DataTemplate.Triggers>
          <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
              <Setter Property="Visibility" TargetName="delimiter" Value="Collapsed"/>
          </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
</ItemsControl.ItemTemplate>

My problem is in delimiter: when ItemsConteol is wrapping to next row then delimiter char goes start of next row.

I understand where is the problem, but I don't know how to sove it.

Result

Thanks in advice.

Author:Sergey Alikin,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/55441714/itemscontrol-wrapping-issue
Vlad :

I have a simple solution with DataTemplateSelector. It goes like this:\n\nYou define a selector, which distinguishes the last item.\n\nclass LastElementSelector : DataTemplateSelector\n{\n public DataTemplate NormalTemplate { get; set; }\n public DataTemplate LastTemplate { get; set; }\n public override DataTemplate SelectTemplate(object item, DependencyObject container)\n {\n return IsLast(container) ? LastTemplate : NormalTemplate;\n }\n\n bool IsLast(DependencyObject container)\n {\n var itemsControl = FindParentOrSelf<ItemsControl>(container);\n var idx = itemsControl.ItemContainerGenerator.IndexFromContainer(container);\n var count = itemsControl.Items.Count;\n return idx == count - 1;\n }\n\n T FindParentOrSelf<T>(DependencyObject from) where T : DependencyObject\n {\n for (var curr = from; curr != null; curr = VisualTreeHelper.GetParent(curr))\n if (curr is T t)\n return t;\n return null;\n }\n}\n\n\nHaving this, you can use different templates for normal and last items:\n\n<ItemsControl ItemsSource=\"{Binding}\">\n <ItemsControl.ItemsPanel>\n <ItemsPanelTemplate>\n <WrapPanel IsItemsHost=\"True\"/>\n </ItemsPanelTemplate>\n </ItemsControl.ItemsPanel>\n <ItemsControl.ItemTemplateSelector>\n <local:LastElementSelector>\n <local:LastElementSelector.NormalTemplate>\n <DataTemplate>\n <TextBlock>\n <Run Text=\"{Binding Mode=OneWay}\"/><!-- no space between runs\n --><Run Text=\"; \" Foreground=\"Red\" FontWeight=\"Bold\"/>\n </TextBlock>\n </DataTemplate>\n </local:LastElementSelector.NormalTemplate>\n <local:LastElementSelector.LastTemplate>\n <DataTemplate>\n <TextBlock Text=\"{Binding}\"/>\n </DataTemplate>\n </local:LastElementSelector.LastTemplate>\n </local:LastElementSelector>\n </ItemsControl.ItemTemplateSelector>\n</ItemsControl>\n\n\nResult:\n\n",
2019-04-01T13:00:49
UsuarioBeta :

Your delimiter goes in front in the next line because it is in front of the LinkId TextBox and both of them are bound together inside a WrapPanel. The whole WrapPanel flows to the next line.\n\nThe parent panel above the WrapPanels does not know and does not care about what is inside them.\n\n\n\nBy the way, I don't know if it was your intention, but in your code as it is written you generate a different WrapPanel for every item in your collection. As it stands, you have 20 WrapPanels in your testlist. \n\nIf, as you say, delimiter after the last is not a problem, this is a good enough solution:\n\n <ItemsControl\n ItemsSource=\"{Binding YourItems}\"\n >\n <ItemsControl.ItemsPanel>\n <ItemsPanelTemplate>\n <WrapPanel\n Orientation=\"Horizontal\"\n ></WrapPanel>\n </ItemsPanelTemplate>\n </ItemsControl.ItemsPanel>\n <ItemsControl.ItemTemplate>\n <DataTemplate>\n <StackPanel\n Orientation=\"Horizontal\"\n >\n <TextBlock\n Text=\"{Binding LinkId}\"\n ></TextBlock>\n <TextBlock\n Text=\"; \"\n ></TextBlock>\n </StackPanel>\n </DataTemplate>\n </ItemsControl.ItemTemplate>\n </ItemsControl>\n\n\nIf this is only for data displaying purposes, consider that those texboxes in line could very much be a single String inside of a TextBox. Maybe you could use a single formatted String and make the relevant parts into Links. This would move the string-delimiter part of the action to the ViewModel and would simplify a lot your XAML code.",
2019-04-01T10:03:10
yy