In a ListView containing Buttons, how to get Index of the clicked one?
Asked Answered
P

3

5

I have a ListView containing only buttons. What I want to do is pretty simple, I want to have the index of the button that has been clicked. The count of the list varies from 0 to 100, so when the user clicks on button 6, I need this number for processing.

I defined my ListView like this:

<ListView Name="myListView" 
          ItemsSource="{Binding Source={StaticResource myDataModel}, 
          Path=StatusList, 
          Mode=OneWay}">
          <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"></StackPanel>
                </ItemsPanelTemplate>
          </ListView.ItemsPanel>

          <ListView.ItemTemplate>
               <DataTemplate>
                    <Button Mode=OneWay}"  
                            Click="Button_Click"/> 
                </DataTemplate>
           </ListView.ItemTemplate>
 </ListView>

My original idea was to create a custom button with an ID and bind the index to the ID but I can't figure out how to do that.

I tried:

int a = myListView.Items.IndexOf(((Button)sender)); 

inside the event handler, but it always returns 0xffffffff can anybody tell me how to get the index of the clicked button?

Propagable answered 5/12, 2011 at 11:4 Comment(2)
why you need the index of the clicked button? hopefully you dont take the index to look for the dataitem??Recor
I need the index of the button because I have to run a query to get the appropriate result of a device connected to the server, and that device has the same number as the buttons indexPropagable
B
2

This should work:

Swap your ListView with an ItemsControl and set an AlternationCount to a very high number (higher than the max count elements in your list). Make a command and pass the current index as a parameter.

XAML:

<Window.CommandBindings>
  <CommandBinding 
   Command="Select" 
   Executed="Click_Executed" />
</Window.CommandBindings>

<ItemsControl AlternationCount="9999" Name="myListView" 
      ItemsSource="{Binding Source={StaticResource myDataModel}, 
      Path=StatusList, 
      Mode=OneWay}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal"></StackPanel>
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Command="Select"
                CommandParameter="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource TemplatedParent}}"
                Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(ItemsControl.AlternationIndex)}" Width="200" Height="20" Click="Button_Click"/>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

Code Behind:

private void Click_Executed(object sender, ExecutedRoutedEventArgs e)
{
  MessageBox.Show("Index: " + e.Parameter.ToString());
}
Barboza answered 5/12, 2011 at 12:39 Comment(3)
This works fine, but when I add a line to change the background using a converter, the converter does not apply. I simply added the following line under the content binding (which I altered to a Tag binding) do you have any idea why? Background="{Binding Source={StaticResource myDataModel}, Path=StatusList, Converter={StaticResource StatusConverter}}"Propagable
I fixed that myself Background="{Converter={StaticResource StatusConverter}}"Propagable
Glad I could help ... If you have problems with bindings in the future have a look in the output window. The errors should be listed there.Barboza
B
31

Use the DataContext to find the item:

var item = (sender as FrameworkElement).DataContext;
int index = myListView.Items.IndexOf(item);
Brookebrooker answered 5/12, 2011 at 11:15 Comment(4)
Thanks for your response, but it now returns 0x00000000 for every clicked item. Maybe because the content is never set?Propagable
This works with DataTemplates in lists such as your example, can you show me your code? Maybe the DataContext property of the button is set differently. If it returns 0 that means it thinks you clicked the first item.Brookebrooker
well except for the sourrounding <Grid><DockPanel> there is no more code. I tried Button 4 and 10, nothing changed.Propagable
Great example Bas. I was trying to figure out how to click an image on a listviewitem and have the handler know which item it was, and this did the trick. Dim item As MyItem = CType(sender, FrameworkElement).DataContext ... thanks!!!!Loiret
B
2

This should work:

Swap your ListView with an ItemsControl and set an AlternationCount to a very high number (higher than the max count elements in your list). Make a command and pass the current index as a parameter.

XAML:

<Window.CommandBindings>
  <CommandBinding 
   Command="Select" 
   Executed="Click_Executed" />
</Window.CommandBindings>

<ItemsControl AlternationCount="9999" Name="myListView" 
      ItemsSource="{Binding Source={StaticResource myDataModel}, 
      Path=StatusList, 
      Mode=OneWay}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal"></StackPanel>
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Command="Select"
                CommandParameter="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource TemplatedParent}}"
                Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(ItemsControl.AlternationIndex)}" Width="200" Height="20" Click="Button_Click"/>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

Code Behind:

private void Click_Executed(object sender, ExecutedRoutedEventArgs e)
{
  MessageBox.Show("Index: " + e.Parameter.ToString());
}
Barboza answered 5/12, 2011 at 12:39 Comment(3)
This works fine, but when I add a line to change the background using a converter, the converter does not apply. I simply added the following line under the content binding (which I altered to a Tag binding) do you have any idea why? Background="{Binding Source={StaticResource myDataModel}, Path=StatusList, Converter={StaticResource StatusConverter}}"Propagable
I fixed that myself Background="{Converter={StaticResource StatusConverter}}"Propagable
Glad I could help ... If you have problems with bindings in the future have a look in the output window. The errors should be listed there.Barboza
A
0

This could work:

private void Button_Click(object sender, EventArgs e)
{
    Button button = (Button)sender;
    MyDataModelElementClass myDataModelElementClass = (MyDataModelElementClass)button.BindingContext;
    var index = myDataModel.IndexOf(myDataModelElementClass);
}
Antiquary answered 3/2, 2021 at 16:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.