0

I am attempting to use a ValueConverter to flip the last item in an ItemsControl (so that it appears backwards).

To accomplish this, I created a Style with a DataTrigger which is using a ValueConverter to check if the current item is the last item in the list.

<UserControl.Resources>
  <local:FIsLastItemInContainerConverter x:Key="IsLastItemInContainerConverter"/>
</UserControl.Resources>

<StackPanel>
  <ItemsControl ItemsSource="{Binding Path=ActiveAction.ActionIconDatas}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <DataTemplate.Resources>
          <Style TargetType="local:FActionInfoControl">
            <Style.Triggers>
              <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource IsLastItemInContainerConverter}}" Value="True">
                <Setter Property="RenderTransformOrigin" Value="0.5 0.5"/>
                <Setter Property="RenderTransform">
                  <Setter.Value>
                    <TransformGroup>
                      <ScaleTransform ScaleX="-1"/>
                    </TransformGroup>
                  </Setter.Value>
                </Setter>
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </DataTemplate.Resources>
        <ContentControl>
          <local:FActionInfoControl/>
        </ContentControl>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
  </ItemsControl>
</StackPanel>

The issue appears to be with my ValueConverter.

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    DependencyObject item = (DependencyObject)value;

    // THIS IS RETURNING NULL
    ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);

    if (ic == null)
    {
        return false;
    }
    else
    {
        return ic.ItemContainerGenerator.IndexFromContainer(item) == ic.Items.Count - 1;
    }
}

Although item is a valid element in the ItemsControl, the call to ItemsControl.ItemsControlFromItemContainer is returning null and I'm not sure why. It is being set, and displays fine (it just is never flipped as the style should cause it to).

Any ideas on this? Thanks!

Goose
  • 1,307
  • 2
  • 14
  • 28

2 Answers2

1

You are passing local:FActionInfoControl to converter, which is not a container for ItemsControl. You need to pass container i.e. ContentPresenter which you can get using FindAncestor.

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                               AncestorType=ContentPresenter, AncestorLevel=2},
                      Converter={StaticResource IsLastItemInContainerConverter}}"
             Value="True">
 .....
</DataTrigger>
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • It doesn't look like ListBoxItem exists on ItemsControl. The Converter is never called with this as a result. – Goose Apr 11 '14 at 17:58
  • Oh yes I overlooked, you are using ItemsControl. For that you have to use ContentPresenter. Update the answer. See if that works. – Rohit Vats Apr 11 '14 at 18:09
  • 1
    Yah, it looks like you and @Didier came up with a similar answer. However, as he mentions "AncestorLevel=2" is required as well. Thanks for the help though!! – Goose Apr 11 '14 at 18:13
1

Try replacing your binding with:

{Binding RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}, AncestorLevel=2}, Converter={StaticResource IsLastItemInContainerConverter}}

Actually ItemsControl.ItemsControlFromItemContainer() only returns parent ItemsControl for actual item containers. In your case ContentPresenter is the container type as you use simple ItemsControl. However as you incapsulate your in a ContentControl in your data template it is important to specify AncestorLevel=2 as well.

Dmitry
  • 2,033
  • 1
  • 22
  • 31
  • ItemsControl.ItemsControlFromItemContainer still fails in this case (returns null). "item" (in the value converter) is coming through as a ContentControl though. – Goose Apr 11 '14 at 18:03
  • Oups my bad Ancestor type should be ContentPresenter and AncestorLevel=2 is needed as well. Because your is incapsulated in an additional ContentControl. – Dmitry Apr 11 '14 at 18:09
  • FYI for other WPF noobs out there: it turned out that was just some legacy stuff. I removed that, and removed AncestorLevel=2 from the binding, and it continued to work. I imagine this might be a more common scenario for people. – Goose Apr 11 '14 at 18:19