WPF ListBoxItems с DataTemplates-как ссылаться на объект CLR, связанный с ListBoxItem из DataTemplate?

у меня есть список, который привязан к ObservableCollection.

каждого ListBoxItem отображается с DataTemplate. У меня есть кнопка в моем DataTemplate, что при нажатии, требуется ссылка на член ObservableCollection это часть DataTemplate для. Я не могу использовать ListBox.SelectedItem свойство, потому что элемент не становится выбранным при нажатии кнопки.

так или иначе: мне нужно выяснить, как правильно установить ListBox.SelectedItem при наведении курсора мыши или при нажатии кнопки. Или Я необходимо выяснить другой способ получить ссылку на объект CLR, привязанный к ListBoxItem что кнопка принадлежит. Второй вариант кажется более чистым, но в любом случае, вероятно, в порядке.

упрощенный фрагмент кода ниже:

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 ответов


вообще говоря, люди будут заинтересованы в объекте CLR, непосредственно связанном с ListBoxItem, а не фактическое 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}"/>

и в вашем коде-позади, ваш Button ' s DataContext равна DataTemplate ' s DataContext. В этом случае 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);
}

у вас есть несколько возможностей, в зависимости от того, что нужно делать.

во-первых, главный вопрос: "зачем тебе это"? В большинстве случаев нет реальной пользы для ссылки на элемент контейнера (не говоря, что это ваш случай, но вы должны уточнить). Если вы привязываете свой список данных, для этого редко бывает случай.

во-вторых, вы можете получить элемент из списка с помощью 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.
}

вы можете найти пример этот блог. Она использует метод index, но метод Item аналогичен.