How get click event from button embedded in each item of ListView?

I have a ListView control with a DataTemplate for displaying some of the columns. Inside of one DataTemplate, I have a button.

When this button is clicked, how do I get the click event in the main window C# code? Will this event also give me the list view item that was clicked, or will I have to figure that out somehow? The button has a name, but that's going to be the same for each row.

Thanks for any help...

[434 byte] By [Redburga] at [2007-12-25]
# 1
you can use

VisualTreeHelper.GetParent(btn) in a loop to go up the tree

leed at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 2

Off the top of my head, you should be able to do this in one of two ways:

  1. Handle the routed click event on your listview - less resources used at runtime, little more logic needed to check what exactly raised the event originally.
  2. Put the event handler declaration on your Button in the DataTemplate's VisualTree - more costly at runtime because every button will have a delegate attached to it, simpler code in the handler since it designed just for that button

HTH,
Drew

DrewMarsh at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 3

Thanks for the suggestions, folks.

Since I could have a few hundred, or even a few thousand items in the list, I probably don't want option 2.

So suppose I want to get the button click event in the window containing the ListView control. The command should bubble up, so I should be able to get it here.

What code do I need to get the button click event so I can handle it and figure out where it came from? I'm guessing I just need to grab any button click and then I could check the name of the control to see if it's the button I care about, then figure where it came from?

I'm stuck on the generic event handler code. I don't have something like MyButton.Click that I can set an event hander to.

Redburga at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 4

Drew, I've thought about your answer a little more...

Is this what you meant by suggestion #2:

<Button Width="16" Height="16" Background="Transparent" Margin="5,0,0,0" Click="EditCommentClick" Name="EditComment" BorderThickness="0,0,0,0" >

I can hande the above using this code:

private void EditCommentClick(object sender, RoutedEventArgs e) {...}

I can then use the VisualTreeHelper.GetParent method that lee suggested. My only concern is if this method causes a delegate to be created for each item in my ListView. I'm still learning how all this stuff gets hooked up.

Thanks for the help..

Redburga at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 5

this is how I did it

<Window x:Class="WindowsApplication1.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WindowsApplication1" Height="300" Width="500" Loaded="OnLoaded"

>

<Grid Width="400">

<Grid.Resources>

<XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">

<x:XData>

<Inventory xmlns="">

<Books>

<Book ISBN="0-7356-0562-9" Stock="in" Number="9">

<Title>XML in Action</Title>

<Summary>XML Web Technology</Summary>

</Book>

<Book ISBN="0-7356-1370-2" Stock="in" Number="8">

<Title>Programming Microsoft Windows With C#</Title>

<Summary>C# Programming using the .NET Framework</Summary>

</Book>

<Book ISBN="0-7356-1288-9" Stock="out" Number="7">

<Title>Inside C#</Title>

<Summary>C# Language Programming</Summary>

</Book>

<Book ISBN="0-7356-1377-X" Stock="in" Number="5">

<Title>Introducing Microsoft .NET</Title>

<Summary>Overview of .NET Technology</Summary>

</Book>

<Book ISBN="0-7356-1448-2" Stock="out" Number="4">

<Title>Microsoft C# Language Specifications</Title>

<Summary>The C# language definition</Summary>

</Book>

</Books>

</Inventory>

</x:XData>

</XmlDataProvider>

<DataTemplate x:Key="res1">

<StackPanel Orientation="Horizontal">

<TextBlock Text="{Binding XPath=@Number}"></TextBlock>

<Button >click here</Button>

</StackPanel>

</DataTemplate>

</Grid.Resources>

<ListView Button.Click="clicked1" Width="400" ItemsSource="{Binding Source={StaticResource InventoryData},

XPath=Book}"

HorizontalAlignment="Center"

VerticalAlignment="Center"

Margin="0,20,0,0" Name="myListView2" >

<ListView.View>

<GridView>

<GridViewColumn Header="ISBN"

DisplayMemberBinding="{Binding XPath=@ISBN}" />

<GridViewColumn Header="Stock"

DisplayMemberBinding="{Binding XPath=@Stock}" />

<GridViewColumn Header="Number"

CellTemplate="{StaticResource res1}"/>

</GridView>

</ListView.View>

</ListView>

</Grid>

</Window>

private DependencyObject GetDependencyObjectFromVisualTree(DependencyObject startObject, Type type)

{

//Iterate the visual tree to get the parent(ItemsControl) of this control

DependencyObject parent = startObject;

while (parent != null)

{

if (type.IsInstanceOfType(parent))

break;

else

parent = VisualTreeHelper.GetParent(parent);

}

return parent;

}

void clicked1(object sender, RoutedEventArgs e)

{

ListViewItem lvi = GetDependencyObjectFromVisualTree(e.OriginalSource as DependencyObject, typeof(ListViewItem)) as ListViewItem;

System.Xml.XmlElement ele = (System.Xml.XmlElement)lvi.Content;

MessageBox.Show("you clicked " + ele.Attributes["ISBN"].Value);

}

leed at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 6

Thanks for the code

I didn't realize I could put the Button.Click in the ListView declaration. It seems to work.

Now, if I have multiple buttons, I believe the Button.Click event handler will get called, regardless of the button. Is there a way to hook the Button.Click event to a specific button name in the xaml? Otherwise, I suppose I can just find the parent to figure out which one was clicked.

Redburga at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 7
Actually, I don't need to look for the parent to figure out which button it is. I just get the button object and ask its name. Then find the parent ListViewItem and I'm ready to go!
Redburga at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 8

How did you accomplish this? I'm trying to find the parent ListViewItem

private void clicked1(Object sender, RoutedEventArgs e)

{

Button b = e.OriginalSource as Button;

ListViewItem lvi = this.listView.ItemContainerGenerator.ItemFromContainer(b) as ListViewItem;

}

clauden at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 9
Hey, Lee, you are just coming a long way to do it, why not just write something like the following in the clicked1 event handler:

private void clicked1(Object sender, RoutedEventArgs e)
{
FrameworkElement fe = e.OriginalSource as FrameworkElement;
System.Xml.XmlElement element = fe.DataContext as System.Xml.XmlElement;
MessageBox.Show(element.Attributes["ISBN"].Value);
}


And if you wannna get the ListViewItem which the clicked button is located, you can do this:

private void clicked1(Object sender, RoutedEventArgs e)
{
FrameworkElement fe = e.OriginalSource as FrameworkElement;
//System.Xml.XmlElement element = fe.DataContext as System.Xml.XmlElement;
//MessageBox.Show(element.Attributes["ISBN"].Value);
ListViewItem lvi = myListView2.ItemContainerGenerator.ContainerFromItem(fe.DataContext) as ListViewItem;
MessageBox.Show(((System.Xml.XmlElement)lvi.Content).Attributes["ISBN"].Value);
}

Sheva


ZhouYong at 2007-9-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...

Visual Studio Orcas

Site Classified