从 ItemsControl 中的模板获取项目

发布于 2024-10-25 03:21:43 字数 709 浏览 1 评论 0原文

我有一个 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?
}

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?
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蹲在坟头点根烟 2024-11-01 03:21:43

好吧,我几乎立即意识到这是“发送者”的“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);
}

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);
}
北恋 2024-11-01 03:21:43

在这种特定情况下,您自己的答案将发挥作用。这是另一种技术,虽然要复杂得多,但无论复杂程度如何,都适用于任何场景:

sender (这是一个 Button)开始,使用 VisualTreeHelper.GetParent 直到您找到一个ContentPresenter。这是您为每个项目指定的 ItemTemplate 托管的 UIElement 类型。我们将 ContentPresenter 放入变量 cp 中。 (重要提示:如果您的 ItemsControlListBox,那么我们将寻找 ListBoxItem 而不是 ContentPresenter代码>等)。

然后,调用 ItemsControl.ItemContainerGenerator.ItemFromContainer (cp)。为此,您需要对特定的 ItemsControl 有一些引用,但这应该不难 - 例如,您可以给它一个 Name 并使用FrameworkElement.FindName 从你的视图本身。 ItemFromContainer 方法将返回您的 ViewModel。

所有这些都是我从 博士 WPF

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文