Get item from template to ItemsControl

I have an ItemsControl that is populated with an observable collection of some ViewModel classes, for example:

<ItemsControl ItemsSource="{Binding MyCollection}">
  <ItemsControl.ItemTemplate>
    <DataTemplate Type="{x:Type local:MyViewModel}">
      <Button Content="{Binding ActionName}" Click="ClickHandler"/>
    </DataTemplate>
  <ItemsControl.ItemTemplate>
</ItemsControl>

      

Works great, looks great, but I can't figure out how to get the "ClickHandler" to know the MyViewModel class that is represented by the data template. Here!

private void ClickHandler(object sender, RoutedEventArgs e)
{
  // The 'sender' is the button that raised the event.  Great!
  // Now how do I figure out the class (MyViewModel) instance that goes with this button?
}

      

+2


source to share


2 answers


Your own answer will do the trick in this particular case. Here's another method, which, although much more complex, will work for any scenario regardless of complexity:

Starting with sender

(which is Button

) use VisualTreeHelper.GetParent

until you find it ContentPresenter

. This is the type UIElement

that is listed ItemTemplate

for each of your items. Let's put ContentPresenter

in a variable cp

. (Important: if yours ItemsControl

was ListBox

, then instead ContentPresenter

we will search ListBoxItem

, etc.).



Then call ItemsControl.ItemContainerGenerator.ItemFromContainer(cp)

. To do this, you will need to have some reference to a specific one ItemsControl

, but it shouldn't be difficult - you can, for example, give it Name

and use FrameworkElement.FindName

from your view. The method ItemFromContainer

will return your ViewModel.

I learned all this from the stupidly useful and opening posts of Dr. WPF .

+4


source


OK, I realized almost immediately that this is the "DataContext" of the "sender". I'm going to leave this behind unless the community thinks the question is too obvious.



private void ClickHandler(object sender, RoutedEventArgs e)
{
  // This is the item that you want.  Many assumptions about the types are made, but that is OK.
  MyViewModel model = ((sender as FrameworkElement).DataContext as MyViewModel);
}

      

+6


source







All Articles