Get item from template in ItemsControl
I have an ItemsControl that is populated with an observable collection of some ViewModel classes, like so:
<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 seem to figure out how to get the "ClickHandler" to be aware of the class 'MyViewModel' that is represented by the data template. Behold!
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?
}
OK duh, I almost immediately realized that it is the 'DataContext' of the 'sender'. I am going to leave this up unless the community thinks that this question is just 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);
}
Your own answer will do the trick in this specific case. Here's another technique which, while much more complicated, will also work on any scenario regardless of complexity:
Starting from sender
(which is a Button
), use VisualTreeHelper.GetParent
until you find a ContentPresenter
. This is the type of UIElement
that the ItemTemplate
you specified is hosted into for each of your items. Let's put that ContentPresenter
into the variable cp
. (Important: if your ItemsControl
were a ListBox
, then instead of ContentPresenter
we 'd look for a ListBoxItem
, etc).
Then, call ItemsControl.ItemContainerGenerator.ItemFromContainer(cp)
. To do that, you will need to have some reference to the specific ItemsControl
but this shouldn't be hard -- you can, for example, give it a Name
and use FrameworkElement.FindName
from your View itself. The ItemFromContainer
method will return your ViewModel.
All of this I learned from the stupidly useful and eye-opening posts of Dr. WPF.
精彩评论