How to track ComboBox selected Index in a WPF application?

MERUN KUMAR MAITY 636 Reputation points
2023-03-13T15:53:47.9866667+00:00

Hello all talented C#, WPF developers. I have a question for you, Suppose I have a Combobox and the ComboBox have four items and I select the second item and I close the Combobox, and suppose the Combobox item source has changed and there more five items are added.

And my previously selected second item is no longer second, it's comes into to the last position. My question is when I open the combobox dropdown next time I want to see the last item as selected item.

I hope you understand, please don't give MVVM base solution, pure code behind solution is welcome.

Developer technologies | Windows Presentation Foundation
Developer technologies | XAML
Developer technologies | XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
Developer technologies | C#
Developer technologies | C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Hui Liu-MSFT 48,711 Reputation points Microsoft External Staff
    2023-03-14T06:08:58.2833333+00:00

    Hi,@MERUN KUMAR MAITY. For setting the second item selected previously becoming the last item, you could try to refer to the following code.

    xaml:

    <StackPanel>
            <Button x:Name="btn" Click="btn_Click" Height="30" Content=" add item"/>
            <ComboBox  x:Name="cmb1" Width="200" Height="60"  ItemsSource="{Binding Icv}" DisplayMemberPath="Name" SelectedItem="{Binding Mode=TwoWay,Path=SelectedItem}" />
        </StackPanel>
    
    

    Codebehind:

    
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    
    namespace ComboboxDemo
    {
    
        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            public int flag = 2;
            private ObservableCollection<AudioDevice> devices = new ObservableCollection<AudioDevice>();
            public ObservableCollection<AudioDevice> Devices
            {
                get { return devices; }
                set
                {
                    if (devices != value)
                    {
                        devices = value;
                      
                        OnPropertyChanged("Devices");
                    }
                }
            }
            private AudioDevice m_selectedItem;
            public AudioDevice SelectedItem
            {
                get { return m_selectedItem; }
                set
                {
                    if (m_selectedItem != value)
                    {
                        m_selectedItem = value;
                        OnPropertyChanged("SelectedItem");
                    }
                }
            }
            private ICollectionView icv;
            public ICollectionView Icv
            {
                get { return icv; }
                set
                {
                    icv = value;
                    OnPropertyChanged("Icv");
                }
            }
            public MainWindow()
            {
                InitializeComponent();
    
                if (flag != null)
                {
                    for (int i = 1; i < 5; i++)
                    {
                        Devices.Add(new AudioDevice() { Name = $"Name{i}", Direction = "Playback", Id = $"{i}", Default = true });
                    }
                    Icv = new ListCollectionView(Devices);
                    
                }
                DataContext = this;
            }
           
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged([CallerMemberName] string name = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
            private void btn_Click(object sender, RoutedEventArgs e)
            {
                Devices.Insert( 0, new AudioDevice() { Name = $"Name{flag}...", Direction = "Recording", Id = $"{flag}", Default = false });
                ObservableCollectionExtensions.Swap(Devices, SelectedItem, Devices.Last());
                SelectedItem = Devices.Last();
                flag++;
            }
        }
        public static class ObservableCollectionExtensions
        {
            public static void Swap<T>(
               this ObservableCollection<T> collection,
               T obj1, T obj2)
            {
                if (!(collection.Contains(obj1) && collection.Contains(obj2))) return;
                var indexes = new List<int>
             {collection.IndexOf(obj1), collection.IndexOf(obj2)};
                if (indexes[0] == indexes[1]) return;
                indexes.Sort();
                var values = new List<T> { collection[indexes[0]], collection[indexes[1]] };
                collection.RemoveAt(indexes[1]);
                collection.RemoveAt(indexes[0]);
                collection.Insert(indexes[0], values[1]);
                collection.Insert(indexes[1], values[0]);
            }
        }
        public class AudioDevice
        {
            public string Name { get; set; }
            public string Direction { get; set; }
            public string Id { get; set; }
            public bool Default { get; set; }
        }
    }
    
    

    The result:

    8


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Peter Fleischer (former MVP) 19,341 Reputation points
    2023-03-14T06:19:29.5+00:00

    Hi,
    you can bind to the collection and to the ComboBox's SelectedItem. If you change the collection and leave SelectedItem unchanged, the original item remains selected even after the collection is changed. Try following demo:

    <Window x:Class="WpfApp1.Window047"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp047"
            mc:Ignorable="d"
            Title="MERUN KUMAR MAITY_230313" Height="450" Width="800">
      <Window.DataContext>
        <local:ViewModel/>
      </Window.DataContext>
      <StackPanel>
        <Button Content="Add Item" Command="{Binding}" Margin="10"/>
        <ComboBox ItemsSource="{Binding ItemsList}" SelectedItem="{Binding SelectedItem}" DisplayMemberPath="Info" Margin="10"/>
      </StackPanel>
    </Window>
    

    ViewModel:

    using System;
    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp047
    {
    	public class ViewModel : ICommand
    	{
    		public ViewModel()
    		{
    			for (index = 1; index < 5; index++) col.Add(new Data() { ID = index, Info = $"Row {index}" });
    			cvs.Source = col;
    		}
    
    		private int index;
    		private Random rnd = new Random();
    
    		private ObservableCollection<Data> col = new ObservableCollection<Data>();
    		private CollectionViewSource cvs = new CollectionViewSource();
    		public object ItemsList { get => cvs.View; }
    
    		public Data SelectedItem { get; set; }
    
    		public event EventHandler? CanExecuteChanged;
    		public bool CanExecute(object? parameter) => true;
    		public void Execute(object? parameter) =>
    			col.Insert(rnd.Next(1, col.Count), new Data() { ID = index++, Info = $"Row {index - 1}" });
    	}
    
    	public class Data
    	{
    		public int ID { get; set; }
    		public string Info { get; set; }
    	}
    }
    

    Result:

    x


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.