WPF ListBoxItems с DataTemplates - Как мне ссылаться на объект CLR, связанный с ListBoxItem из DataTemplate? - PullRequest
9 голосов
/ 20 апреля 2009

У меня есть ListBox, привязанный к 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 ]

12 голосов
/ 20 апреля 2009

Вообще говоря, людям будет интересен объект 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 DataContext равны вашим DataTemplate * 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);
}
3 голосов
/ 20 апреля 2009

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

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

Во-вторых, вы можете получить элемент из списка, используя myListBox.ItemContainerGenerator.ContainerFromItem(), при условии, что ваш список имеет имя MyListBox. Из параметра отправителя вы можете получить обратно фактический элемент, через который был выполнен шаблон, например (где XXX - это тип данных, привязанных к вашей базе данных):

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

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

...