How to track ComboBox selected Index in a WPF application?

MERUN KUMAR MAITY 511 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.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,671 questions
C#
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.
10,247 questions
XAML
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.
765 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Hui Liu-MSFT 38,251 Reputation points Microsoft Vendor
    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,231 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