views:

288

answers:

4

I have a list box with a data template. The template has a button on it. When the button is clicked I want to do some logic with the object that is each row (in this cased an object called WorkItemTypeMappings).

In the OnClick how can I go from the Button (object sender) to the object that is row that the button is on?

Here is the XAML of my list box:

<ListBox ItemsSource="{Binding Source={StaticResource WorkItemTypeMappingsCollectionView}}" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Name="lstWITypes">
    <ListBox.GroupStyle>
        <x:Static Member="GroupStyle.Default"/>
    </ListBox.GroupStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*"/>
                    <ColumnDefinition Width="2*"/>
                    <ColumnDefinition Width="50"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding SourceType, Converter={StaticResource WorkItemTypeToStringConverter}}"/>
                <ComboBox Grid.Column="1" SelectedItem="{Binding DestType}" ItemsSource="{Binding WorkItemTypesForCurrentDestProject, Source={x:Static loc:MainMediator.Instance}, diagnostics:PresentationTraceSources.TraceLevel=High}" DisplayMemberPath="Name" />

                <!-- This is the button-->
                <Button Grid.Column="2" Content="{Binding PercentMapped}" 
                        Click="ManualMappingClick"/>
            </Grid>
        </DataTemplate>                                        
    </ListBox.ItemTemplate>
</ListBox>
A: 

have you tried ListBox.SelectedItem?

Muad'Dib
Yes. However, it is possible to click the button and not select the item (I checked)
Vaccano
+1  A: 

Try using VisualTreeHelper to find the parent ListBoxItem for the button. A few good general all-purpose helper functions can be found here:

http://stackoverflow.com/questions/636383/wpf-ways-to-find-controls

so, for example, you could find the ListBoxItem from the click event with a call like this:

ListBoxItem item = UIHelper.FindVisualParent<ListBoxItem>(sender);
sdcoder
I don't need the ListBoxItem. I need the data behind it. (As I said in my question: "with the object that is each row (in this cased an object called WorkItemTypeMappings)"
Vaccano
The ListBoxItem is the "data behind it". Once you have the ListBoxItem, you should just be able to cast it like this:WorkItemTypeMappings dataObject = item as WorkItemTypeMappings;
sdcoder
A: 

Additionally, if you have a reference to the ListBoxControl already, and you also have the data item representing the row (I assume so since you have the binding, and thus can drag it out of the DataContext on the button), you can ask the ItemsContainerGenerator. ContainerFromItem to give you give you the actual UIElement for the row.

The itemcontainergenerator can be found as a property on the listview itself. (technically the itemscontrol, since thats where it's defined)

dhopton
I am actually looking to go the other way. I need the data item representing the row.
Vaccano
+2  A: 

What you can do as an alternative is to use Command instead of Event. If you bind your button to a command and pass along with it a command parameter, you should be able to get the item that is related to that button. Example code:

<!-- This is the button-->
 <Button
     Grid.Column="2"
     Content="{Binding PercentMapped}" 
     Command="SolutionNamespace:CommandClass.ButtonClickedCommand"
     CommandParameter="{Binding}" />

I am not sure how familiar you are with WPF commanding but you will notice that the CommandParameter binds to the context without a path name, that is to say it binds to the WorkItemTypeMappings that you need.

Command Example Code:

public static SimpleCommand ButtonClickedCommand { get; set; }

static CommandClass()
{
    ButtonClickedCommand = new SimpleCommand
                           {
                               ExecuteDelegate =
                               x=> ButtonClicked(x as WorkItemTypeMappings)
                           };
}


public static ButtonClicked(WorkItemTypeMappings mappings)
{
    if(mappings != null) MessageBox.Show(mapping.PercentMapped)
}

You will notice that the ButtonClickedCommand is static, this is required because the button cannot access the command from its current binding context.

SimpleCommand is just a simplified implementation of the ICommand, can Google this one if you're not sure. I hope this is not an overkill to your problem, but you cannot go wrong with WPF Commands.

Good luck.

Tri Q
Good stuff here. I have been wanting to try my hand at commands. This will be a good trial. I will try it out and accept if it works out.
Vaccano
That worked fantastic! And I feel like I did it the "right way". Thanks for the great answer.
Vaccano
I'm glad you got it to work given my minimal code snippets. You are most welcome.
Tri Q