【问题标题】:WPF ListBoxItems with DataTemplates - How do I reference the CLR Object bound to ListBoxItem from within the DataTemplate?带有 DataTemplates 的 WPF ListBoxItems - 如何从 DataTemplate 中引用绑定到 ListBoxItem 的 CLR 对象?
【发布时间】:2010-10-20 10:35:26
【问题描述】:

我有一个 ListBox,它绑定到 ObservableCollection

每个ListBoxItem 都以DataTemplate 显示。我的DataTemplate 中有一个按钮,单击该按钮时需要引用ObservableCollection 的成员,它是DataTemplate 的一部分。我无法使用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?");
}

【问题讨论】:

    标签: wpf listbox datatemplate listboxitem


    【解决方案1】:

    您有多种可能性,具体取决于您需要做什么。

    首先,主要问题是:“为什么需要这个”?大多数时候,对容器项的引用并没有真正的用处(不是说这是你的情况,但你应该详细说明)。如果您正在对列表框进行数据绑定,则很少有这种情况。

    其次,您可以使用myListBox.ItemContainerGenerator.ContainerFromItem() 从列表框中获取项目,前提是您的列表框名为MyListBox。从 sender 参数中,您可以取回模板化的实际项目,例如(其中XXX 是您的数据绑定数据的类型):

    Container = sender as FrameworkElement;
    if(sender != null)
    {
        MyItem = Container.DataContext as XXX;
        MyElement = MyListBox.ItemContainerGenerator.ContainerFromItem(MyItem); // <-- this is your ListboxItem.
    }
    

    您可以在this blog 中找到一个示例。她用的是index方法,不过Item方法也差不多。

    【讨论】:

    • 对问题的原始措辞很好的回答。 Bendewey 正确地假设我不是我所说的我所做的,但这也是值得赞赏的。投票赞成。
    【解决方案2】:

    一般来说,人们会对直接绑定到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 本身。
    猜你喜欢
    • 2011-02-16
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多