template - wpf dropdown
WPF ListBoxItems con DataTemplates-¿Cómo hago referencia al objeto CLR vinculado a ListBoxItem desde el DataTemplate? (2)
Tengo un ListBox, que está vinculado a un ObservableCollection
.
Cada ListBoxItem
se muestra con un DataTemplate
. Tengo un botón en mi DataTemplate
, que cuando hace clic, necesita una referencia al miembro de ObservableCollection
cual es parte de DataTemplate. No puedo usar la propiedad ListBox.SelectedItem
porque el elemento no se selecciona al hacer clic en el botón.
Entonces, o bien: necesito descubrir cómo establecer correctamente ListBox.SelectedItem
cuando el mouse se ListBox.SelectedItem
, o cuando se hace clic en el botón. O tengo que encontrar otra forma de obtener una referencia al objeto CLR vinculado al ListBoxItem
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}"/>
DO#:
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("Where mah ListBoxItem?");
}
Tienes varias posibilidades, dependiendo de lo que necesites hacer.
Primero, la pregunta principal es: "¿por qué necesitas 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 debes elaborarlo). 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 MyListBox
se llame MyListBox
. Desde el parámetro del remitente, puede recuperar el elemento real al que se le ha aplicado la plantilla, por ejemplo (donde XXX
es el tipo de sus datos de datos):
Container = sender as FrameworkElement;
if(sender != null)
{
MyItem = Container.DataContext as XXX;
MyElement = MyListBox.ItemContainerGenerator.ContainerFromItem(MyItem); // <-- this is your ListboxItem.
}
Puedes encontrar un ejemplo y este blog . Ella usa el método de índice, pero el método de artículo es similar.
En términos generales, las personas estarán interesadas en un objeto CLR directamente vinculado al ListBoxItem
, no en el ListBoxItem
real. Si tuviera una lista de publicaciones, por ejemplo, podría usar 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, el DataContext
su Button
es igual al DataContext
de su DataTemplate
. 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);
}