0

I've been researching this for a while and to no avail (I've tried to get command working but there is somethign I'm seriously missing I think. Very new to WPF's way of doing things which isn't helping (but really liking what I find with WPF)

I'm have the same issue as this post: Get the ListBox row object from a button that is on the DataTemplate

I have a listbox with labels + 2 buttons in each datatemplate. I need t know which row is being clicked when the button is clicked. (The row is not selected at all so Selectedindex is out the question). I really like Vaccano's method but can't seem to get it to work on the informatin he has given (he states himself it is very brief)

<ListBox x:Name="lbDirectoryTreeBox" Height="auto" Width="auto" Grid.Column="0" Grid.Row="0" Margin="10,10,5,10" ItemsSource="{Binding}" 
            MouseDoubleClick="lbDirectoryBox_MouseDoubleClick" SelectionChanged="lbDirectoryTreeBox_SelectionChanged">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">                        
                <Button x:Name="btnOpenFolder" Content="R" Width="20" Height="20" Click="btnDirectoryOpen_Click" />
                <Button x:Name="btnAddFolder" Content="R" Width="20" Height="20" Click="btnAddFolder_Click" />
                <Label Width="auto" Content="{Binding Path=Name}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

How can I get the selectedindex of the row after clicking either of the buttons? (in c#)

Thanks in advance for any help here.

Community
  • 1
  • 1
Oli
  • 428
  • 1
  • 5
  • 20

3 Answers3

5

Buttons in the data template will inherit data context from the list box item, so you can use something like:

private void btnDirectoryOpen_Click(object sender, RoutedEventArgs e)
{
    var item = ((Button) sender).DataContext;
    var itemIndex = lbDirectoryTreeBox.Items.IndexOf(item);
    // ...
}
Sergii Volchkov
  • 1,169
  • 17
  • 23
  • After trying this mehtod and the command method I've resorted to using this method. Is there any drawbacks to this? @Gimno method is how the previous aricle attempted it and it seems odd if it really is this simple. – Oli Mar 21 '11 at 09:27
  • @Oli: Gimno's method with FindAncestor binding gives you immediate access to the item's container; with the described approach, you will have to use additional code to find it - e.g. using ContainerFromItem/ContainerFromIndex methods of lbDirectoryTreeBox.ItemContainerGenerator, or by performing visual parent lookup. – Sergii Volchkov Mar 23 '11 at 17:38
1

You can use a CommandParameter to get the row you want:

CommandParameter="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}

So, if you want to use this, you have to assign a Command to your button and use it as command parameter, e.g.:

<Button x:Name="btnOpenFolder" Content="R" Width="20" Height="20" Command="Help" CommandParameter="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />

and you have to create CommandBindings for your Window/Page/UserControl, for example:

<Window.CommandBindings>
    <CommandBinding Command="Help" Executed="btnDirectoryOpen_Command" />
</Window.CommandBindings>

(Using "Help" as command here is not a good example, you should replace it with something better)

In your method in the CodeBehind- File, you can get the ListBoxItem with e.Parameter:

private void btnDirectoryOpen_Command(object sender, ExecutedRoutedEventArgs e)
{
  var item = e.Parameter;  
}

Further readings: How to enable commands

Gimno
  • 6,506
  • 3
  • 39
  • 39
0

If you have a limited number of rows you could set the AlternationIndex to something really high and use that as a CommandParameter

<Button CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(ItemsControl.AlternationIndex)}" />
Rachel
  • 130,264
  • 66
  • 304
  • 490