WPF ListBoxItems与DataTemplates - 如何在DataTemplate中引用绑定到ListBoxItem的CLR对象?

9

我有一个ListBox,它绑定了一个ObservableCollection。

每个ListBoxItem都使用DataTemplate显示。我的DataTemplate中有一个按钮,当点击它时,需要引用它所属的ObservableCollection成员。我无法使用ListBox.SelectedItem属性,因为在单击按钮时该项不会被选中。

因此:我需要找出如何在鼠标悬停或单击按钮时正确设置ListBox.SelectedItem。或者我需要找到另一种方法来获取与按钮所属的ListBoxItem绑定的CLR对象的引用。第二个选项似乎更清晰,但任何一种方式都可以。

以下是简化的代码段:

XAML:

<DataTemplate x:Key="postBody">
    <Grid>
        <TextBlock Text="{Binding Path=author}"/>
        <Button Click="DeleteButton_Click">Delete</Button>
    </Grid>
</DataTemplate>

<ListBox ItemTemplate="{StaticResource postBody}"/>

C#:

private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine("Where mah ListBoxItem?");
}
2个回答

12

一般来说,人们对直接绑定到ListBoxItem的CLR对象更感兴趣,而不是实际的ListBoxItem。例如,如果您有一些帖子的列表,您可以使用现有的模板:

<DataTemplate x:Key="postBody" TargetType="{x:Type Post}">
  <Grid>
    <TextBlock Text="{Binding Path=author}"/>
    <Button Click="DeleteButton_Click">Delete</Button>
  </Grid>
</DataTemplate>
<ListBox ItemTemplate="{StaticResource postBody}" 
  ItemSource="{Binding Posts}"/>

在您的代码后端,您的ButtonDataContext等于您的DataTemplateDataContext。在这种情况下是一个Post

private void DeleteButton_Click(object sender, RoutedEventArgs e){
  var post = ((Button)sender).DataContext as Post;
  if (post == null)
    throw new InvalidOperationException("Invalid DataContext");

  Console.WriteLine(post.author);
}

这很完美,而且您还修正了我的问题措辞。我会进行编辑,因为您是正确的,我对绑定的CLR对象感兴趣,而不是ListBoxItem本身。 - John Noonan

3
你有几种可能性,取决于你需要做什么。
首先,主要问题是:“为什么需要这个”?大多数情况下,没有真正使用容器项的参考(不是说这是你的情况,但你应该详细说明)。如果你正在数据绑定列表框,很少有这种情况。
其次,你可以使用 myListBox.ItemContainerGenerator.ContainerFromItem() 从 Listbox 获取项目,前提是你的列表框命名为 MyListBox。通过 sender 参数,你可以获取实际经过模板化的项目,例如(其中 XXX 是你数据绑定数据的类型):
Container = sender as FrameworkElement;
if(sender != null)
{
    MyItem = Container.DataContext as XXX;
    MyElement = MyListBox.ItemContainerGenerator.ContainerFromItem(MyItem); // <-- this is your ListboxItem.
}

你可以在这篇博客中找到一个例子。她使用了索引方法,但 Item 方法也类似。

对于最初的问题,这是一个很好的回答。bendewey 正确地假设我并不是说了我所说的话,但这也受到赞赏。投票支持。 - John Noonan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接