开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜