1

I have an ItemsControl nested inside a ListBox.ItemTemplate. The top ListBox is data-bound to an ObservableCollection. The collection is essentially a Purchase which contains Formulae which in turn contain individual products.

Now, if an individual product inside a formula is clicked, I would like it to be deleted from its formula. So, in the event handler, I should be able to determine the product's position using:

var index = [theItemsControl].ItemContainerGenerator.IndexFromContainer((sender as Button).TemplatedParent);

However, in my event handler, I do not how how to find the containing ItemsControl. I cannot give it a fixed name, since it is itself a part of a ListBox.ItemTemplate, meaning there will be multiple instances.

This is my XAML, stripped of any style-related stuff:

<ListBox x:Name="lbBasketFormulae" ItemsSource="{Binding Path=Purchase.Formulae}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Vertical">

        <!-- Formula Title -->
        <StackPanel Orientation="Horizontal">
          <Label Width="30" Content="{Binding Path=Quantity}"></Label>
          <Label Content="{Binding Path=FormulaType, Converter={StaticResource formulaTypeToNameConverter}}"></Label>
        </StackPanel>

        <!-- Formula Products -->
        <ItemsControl ItemsSource="{Binding Path=Products}">
          <ItemsControl.ItemTemplate>
            <DataTemplate>
              <Button x:Name="bnBasketFormulaProduct" HorizontalContentAlignment="Left" Content="{Binding Path=Name}" Click="bnBasketFormulaProduct_Click">
                <Button.Template>
                  <ControlTemplate TargetType="Button">
                    <TextBlock Text="{TemplateBinding Content}" />
                  </ControlTemplate>
                </Button.Template>
              </Button>
            </DataTemplate>
          </ItemsControl.ItemTemplate>
        </ItemsControl>

      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

So, my question is: How do I find the position of my product inside my formula and the position of that formula inside the purchase, so that I can remove it from the ObservableCollection? (Changing the collection should then automatically reflect to the UI since it is data-bound.)

Many thanks in advance for any advice or hints!

Regards,

Chris

Christophe
  • 354
  • 3
  • 16

2 Answers2

0

The answer is you don't find any positions of anything using ItemContainerGenerator.IndexFromContainer. Your problem is clearly taking place inside ViewModel and therefore you should seek for selected item or whatever inside your ViewModel and not in ListBox or code behind of Window.

Therefore I suggest you to create a proper ViewModel with proper Bindings.

dev hedgehog
  • 8,698
  • 3
  • 28
  • 55
  • Thank you, but I am currently not implementing the MVVM pattern. I am new to WPF/XAML and it is hard enough as it is. – Christophe Feb 21 '14 at 13:18
  • I can understand you want to keep things simple. I sometimes feel like punching the guy who convinced us to move to WPF, because simple things can take so much longer. But be careful your logic doesn't become tied to your controls as that leads to a LOT more work. WPF bug finding is not nice. Please see this thread for some excelent tips that really helped me: http://stackoverflow.com/questions/8863840/developing-wpf-software-without-mvvm – David Feb 21 '14 at 13:32
0

It is true that you should be able to do it via the viewmodel. But if you want you could use:

VisualTreeHelper.GetParent(myUserControl);
David
  • 853
  • 8
  • 24
  • Thank you. Using this method, I was able to access the parent's datacontext which is eventually even more useful and reliable than merely the index I wanted in the first place. – Christophe Feb 21 '14 at 13:20