2009-04-19 10 views
8

Tengo un ListBox, que está vinculado a un ObservableCollection.WPF ListBoxItems con DataTemplates - ¿Cómo hago referencia al objeto CLR vinculado a ListBoxItem desde el DataTemplate?

Cada ListBoxItem se muestra con DataTemplate. Tengo un botón en mi DataTemplate, que cuando hace clic, necesita una referencia al miembro del ObservableCollection para el que es parte de DataTemplate. No puedo usar la propiedad ListBox.SelectedItem porque el elemento no se selecciona al hacer clic en el botón.

O bien: Necesito averiguar cómo configurar correctamente ListBox.SelectedItem cuando el mouse se desplaza, o cuando se hace clic en el botón. O necesito encontrar otra forma de obtener una referencia al objeto CLR vinculado al ListBoxItem al que pertenece el botón. La segunda opción parece más limpia, pero de todos modos es probable que esté bien.

segmento de código simplificado a continuación:

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?"); 
} 

Respuesta

11

personas que hablan generalmente estará interesado en un objeto de CLR directamente unido al ListBoxItem, no el real ListBoxItem. Si usted tenía una lista de mensajes, por ejemplo, usted podría utilizar su plantilla existente de:

<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}"/> 

y en su código subyacente, sus Button 's DataContext es igual a sus DataTemplate' s DataContext. En este caso, un 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); 
} 
+0

Esto es perfecto, y también has arreglado la redacción de mi pregunta. Lo editaré porque tiene razón, estoy interesado en el objeto CLR encuadernado, no en el ListBoxItem mismo. –

3

Tiene varias posibilidades, dependiendo de lo que necesite hacer.

En primer lugar, la pregunta principal es: "¿por qué necesita esto?" La mayoría de las veces, no hay un uso real para una referencia al artículo del contenedor (no diciendo que este es tu caso, pero deberías dar más detalles). Si está vinculando su lista de datos, rara vez hay un caso para eso.

En segundo lugar, puede obtener el elemento del Listbox, utilizando myListBox.ItemContainerGenerator.ContainerFromItem(), siempre que su cuadro de lista se llame MyListBox. Desde el parámetro emisor, puede volver el artículo, de lo que fue templated a través, por ejemplo (donde XXX es el tipo de datos de enlace de datos):

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

Usted puede encontrar un ejemplo de un this blog. Ella usa el método de índice, pero el método de artículo es similar.

+0

Buena respuesta a la pregunta como está redactada originalmente. Bendewey asumió correctamente que no quise decir lo que dije que hice, pero esto también es apreciado. Votado arriba. –

Cuestiones relacionadas