从ItemsControl中的模板中获取项目

时间:2011-03-23 03:00:27

标签: c# wpf templates xaml

我有一个ItemsControl,其中填充了一些ViewModel类的可观察集合,如下所示:

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

效果很好,看起来很棒,但我似乎无法弄清楚如何让“ClickHandler”知道由数据模板表示的类“MyViewModel”。看哪!

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 个答案:

答案 0 :(得分:7)

好吧,我几乎立即意识到它是'发送者'的'DataContext'。除非社区认为这个问题太明显,否则我会放弃这一点。

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);
}

答案 1 :(得分:4)

在这个具体案例中,您自己的答案将起到作用。这是另一种技术,虽然复杂得多,但也适用于任何场景,无论复杂程度如何:

senderButton)开始,使用VisualTreeHelper.GetParent,直至找到ContentPresenter。这是UIElement的类型,您为每个商品托管了ItemTemplate。我们将ContentPresenter放入变量cp。 (重要提示:如果您的ItemsControlListBox,那么我们会代替ContentPresenter寻找ListBoxItem)。

然后,拨打ItemsControl.ItemContainerGenerator.ItemFromContainer(cp)。要做到这一点,您需要参考具体的ItemsControl,但这应该不难 - 例如,您可以给它一个Name并使用FrameworkElement.FindName来自你的观点本身。 ItemFromContainer方法将返回您的ViewModel。

所有这一切都是从Dr. WPF的愚蠢有用且令人大开眼界的帖子中学到的。