Home > OS >  Get the index of clicked ObservableCollection item in WPF?
Get the index of clicked ObservableCollection item in WPF?

Time:07-18

This may be an easy question but I have looked around for the answer nearly an hour. So here it goes:

I have an ObservableCollection of numbers, all are 10 and they are shown as buttons. When one from left is clicked, it will decrease it's value and increase the value on the right.

In View, it is defined as below:

<UniformGrid x:Name="Nums" Grid.Row="1" Rows="1">
                <local:Nums="{Binding Numbers[0]}" Stroke="Red" Click="Button_Clicked" />
                <local:Nums="{Binding Numbers[1]}" Stroke="Red" Click="Button_Clicked" />
                <local:Nums="{Binding Numbers[2]}" Stroke="Red" Click="Button_Clicked" />
                <local:Nums="{Binding Numbers[3]}" Stroke="Red" Click="Button_Clicked" />
                <local:Nums="{Binding Numbers[4]}" Stroke="Red" Click="Button_Clicked" />
                <local:Nums="{Binding Numbers[5]}" Stroke="Red" Click="Button_Clicked" />
</UniformGrid>

Numbers is an ObservableCollection and has the necessary PropertyChangedEvent inside the viewmodel.

private ObservableCollection<int> numbers = new ObservableCollection<int>() { 10, 10, 10, 10, 10, 10 };
        public ObservableCollection<int> Numbers
        {
            get => Numbers;
            set
            {
                if (value != Numbers)
                {
                    Numbers = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Numbers)));
                }
            }
        }

When the button is clicked it triggers the View but I don't know how to get which value and index of the ObservableCollection is clicked?

using NumberChanger.ViewModels;
using System;
using System.Windows;
using System.Windows.Controls;

namespace NumberChanger.Views
{

    public partial class NumberChanger : UserControl
    {
        NumberChangerViewModel numberChangerViewModel = new NumberChangerViewModel();
        public NumberChangerViewModel()
        {
            
            this.DataContext = numberChangerViewModel;
            InitializeComponent();
        }

        private void Button_Clicked(object sender, RoutedEventArgs e)
        {
            Console.WriteLine(numberChangerViewModel.Numbers);
            
            throw new NotImplementedException();
        }
    }
}

EDIT:

Added Nums class

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace NumberChanger.Views
{

    public partial class Nums : Button
    {
      

        public int Nums
        {
            get { return (int)GetValue(NumsProperty); }
            set { SetValue(NumsProperty, value); }
        }

        public static readonly DependencyProperty NumsProperty = DependencyProperty.Register(
            nameof(Nums),
            typeof(int),
            new PropertyMetadata(0)
        );

        public Nums()
        {
            InitializeComponent();
        }
    }
}

CodePudding user response:

Since you have a not unique collection of int (value type).. there is no possibility to find index in collection by value. You can find index of clicked control - it will be same as index value in the ObservableCollection in your case.

using NumberChanger.ViewModels;
using System;
using System.Windows;
using System.Windows.Controls;

namespace NumberChanger.Views
{

    public partial class NumberChanger : UserControl
    {
        NumberChangerViewModel numberChangerViewModel = new NumberChangerViewModel();
        public NumberChangerViewModel()
        {
            
            this.DataContext = numberChangerViewModel;
            InitializeComponent();
        }

        private void Button_Clicked(object sender, RoutedEventArgs e)
        {
            // button inside your local:Nums
            var button = sender as Button;

            // index of control in the UniformGrid which is related to the index in collection
            int index = this.Nums.Children.IndexOf(button); 

            Console.WriteLine(index); 
        }
    }
}
  • Related