Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6055633
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T08:17:10+00:00 2026-05-23T08:17:10+00:00

Lets say we got a simple VM class public class PersonViewModel : Observable {

  • 0

Lets say we got a simple VM class

public class PersonViewModel : Observable
    {
        private Person m_Person= new Person("Mike", "Smith");

        private readonly ObservableCollection<Person> m_AvailablePersons =
            new ObservableCollection<Person>( new List<Person> {
               new Person("Mike", "Smith"),
               new Person("Jake", "Jackson"),                                                               
        });

        public ObservableCollection<Person> AvailablePersons
        {
            get { return m_AvailablePersons; }
        }

        public Person CurrentPerson
        {
            get { return m_Person; }
            set
            {
                m_Person = value;
                NotifyPropertyChanged("CurrentPerson");
            }
        }
    }

It would be enough to successfully databind to a ComboBox for example like this:

<ComboBox ItemsSource="{Binding AvailablePersons}" 
          SelectedValue="{Binding Path=CurrentPerson, Mode=TwoWay}" />

Notice that Person has Equals overloaded and when I set CurrentPerson value in ViewModel it causes combobox current item to display new value.

Now lets say I want to add sorting capabilities to my view using CollectionViewSource

 <UserControl.Resources>
        <CollectionViewSource x:Key="PersonsViewSource" Source="{Binding AvailablePersons}">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="Surname" Direction="Ascending" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </UserControl.Resources>

Now combobox items source binding will look like this:

<ComboBox ItemsSource="{Binding Source={StaticResource PersonsViewSource}}"
          SelectedValue="{Binding Path=CurrentPerson, Mode=TwoWay}" />    

And it will be indeed sorted (if we add more items its clearly seen).

However when we change CurrentPerson in VM now (before with clear binding without CollectionView it worked fine) this change isn’t displayed in bound ComboBox.

I believe that after that in order to set CurrentItem from VM we have to somehow access the View (and we dont go to View from ViewModel in MVVM), and call MoveCurrentTo method to force View display currentItem change.

So by adding additional view capabilities (sorting ) we lost TwoWay binding to existing viewModel which I think isn’t expected behaviour.

Is there a way to preserve TwoWay binding here ? Or maybe I did smth wrong.

EDIT: actually situation is more complicated then it may appear, when I rewrite CurrentPerson setter like this:

set
{
    if (m_AvailablePersons.Contains(value)) {
       m_Person = m_AvailablePersons.Where(p => p.Equals(value)).First();
    }
    else throw new ArgumentOutOfRangeException("value");
    NotifyPropertyChanged("CurrentPerson");

}

it works fine!

Its buggy behaviour, or is there an explanation? For some reasons even though Equals is overloaded it requires reference equality of person object.

I really don’t understand why It needs reference equality so I am adding a bounty for someone who can explain why normal setter doesn’t work, when Equal method is overloaded which can clearly be seen in “fixing” code that uses it

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T08:17:11+00:00Added an answer on May 23, 2026 at 8:17 am

    There are 2 problems ganging up on you, but you have highlighted a real problem with using CollectionViewSource with a ComboBox. I am still looking for alternatives to fix this in a “better way”, but your setter fix avoids the problem for good reason.

    I have reproduced your example in full detail to confirm the problem and a theory about the cause.

    ComboBox binding to CurrentPerson does not use the equals operator to find a match IF YOU USE SelectedValue INSTEAD OF SelectedItem. If you breakpoint your override bool Equals(object obj) you will see it is not hit when you change the selection.

    By changing your setter to the following, you are finding a specific matching object, using your Equals operator, so a subsequent value compare of 2 objects will work.

    set
    {
        if (m_AvailablePersons.Contains(value)) {
           m_Person = m_AvailablePersons.Where(p => p.Equals(value)).First();
        }
        else throw new ArgumentOutOfRangeException("value");
        NotifyPropertyChanged("CurrentPerson");
    
    }
    

    Now the really interesting result:

    Even if you change your code to use SelectedItem, it will work for a normal binding to the list but still fail for any binding to the sorted view!

    I added debug output to the Equals method and even though matches were found, they were ignored:

    public override bool Equals(object obj)
    {
        if (obj is Person)
        {
            Person other = obj as Person;
            if (other.Firstname == Firstname && other.Surname == Surname)
            {
                Debug.WriteLine(string.Format("{0} == {1}", other.ToString(), this.ToString()));
                return true;
            }
            else
            {
                Debug.WriteLine(string.Format("{0} <> {1}", other.ToString(), this.ToString()));
                return false;
            }
        }
        return base.Equals(obj);
    }
    

    My conclusion…

    …is that behind the scenes the ComboBox is finding a match, but because of the presence of the CollectionViewSource between it and the raw data it is then ignoring the match and comparing objects instead (to decide which one was selected). From memory a CollectionViewSource manages its own current selected item, so if you do not get an exact object match it will never work using a CollectionViewSource with a ComboxBox.

    Basically your setter change works because it guarantees an object match on the CollectionViewSource, which then guarantees an object match on the ComboBox.

    Test code

    The full test code is below for those that want to play (sorry about the code-behind hacks, but this was just for testing and not MVVM).

    Just create a new Silverlight 4 application and add these files/changes:

    PersonViewModel.cs

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    namespace PersonTests
    {
        public class PersonViewModel : INotifyPropertyChanged
        {
            private Person m_Person = null;
    
            private readonly ObservableCollection<Person> m_AvailablePersons =
                new ObservableCollection<Person>(new List<Person> {
                   new Person("Mike", "Smith"),
                   new Person("Jake", "Jackson"),                                                               
                   new Person("Anne", "Aardvark"),                                                               
            });
    
            public ObservableCollection<Person> AvailablePersons
            {
                get { return m_AvailablePersons; }
            }
    
            public Person CurrentPerson
            {
                get { return m_Person; }
                set
                {
                    if (m_Person != value)
                    {
                        m_Person = value;
                        NotifyPropertyChanged("CurrentPerson");
                    }
                }
    
                //set // This works
                //{
                //  if (m_AvailablePersons.Contains(value)) {
                //     m_Person = m_AvailablePersons.Where(p => p.Equals(value)).First();
                //  }
                //  else throw new ArgumentOutOfRangeException("value");
                //  NotifyPropertyChanged("CurrentPerson");
                //}
            }
    
            private void NotifyPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    
        public class Person
        {
            public string Firstname { get; set; }
            public string Surname { get; set; }
    
            public Person(string firstname, string surname)
            {
                this.Firstname = firstname;
                this.Surname = surname;
            }
    
            public override string ToString()
            {
                return Firstname + "  " + Surname;
            }
    
            public override bool Equals(object obj)
            {
                if (obj is Person)
                {
                    Person other = obj as Person;
                    if (other.Firstname == Firstname && other.Surname == Surname)
                    {
                        Debug.WriteLine(string.Format("{0} == {1}", other.ToString(), this.ToString()));
                        return true;
                    }
                    else
                    {
                        Debug.WriteLine(string.Format("{0} <> {1}", other.ToString(), this.ToString()));
                        return false;
                    }
                }
                return base.Equals(obj);
            }
        }
    }
    

    MainPage.xaml

    <UserControl x:Class="PersonTests.MainPage"
        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:scm="clr-namespace:System.ComponentModel;assembly=System.Windows" mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
        <UserControl.Resources>
            <CollectionViewSource x:Key="PersonsViewSource" Source="{Binding AvailablePersons}">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="Surname" Direction="Ascending" />
                </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>
        </UserControl.Resources>
        <StackPanel x:Name="LayoutRoot" Background="LightBlue" Width="150">
            <!--<ComboBox ItemsSource="{Binding AvailablePersons}"
                  SelectedItem="{Binding Path=CurrentPerson, Mode=TwoWay}" />-->
            <ComboBox ItemsSource="{Binding Source={StaticResource PersonsViewSource}}"
              SelectedItem="{Binding Path=CurrentPerson, Mode=TwoWay}" />
            <Button Content="Select Mike Smith" Height="23" Name="button1" Click="button1_Click" />
            <Button Content="Select Anne Aardvark" Height="23" Name="button2" Click="button2_Click" />
        </StackPanel>
    </UserControl>
    

    MainPage.xaml.cs

    using System.Windows;
    using System.Windows.Controls;
    
    namespace PersonTests
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
                this.DataContext = new PersonViewModel();
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                (this.DataContext as PersonViewModel).CurrentPerson = new Person("Mike", "Smith");
            }
    
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                (this.DataContext as PersonViewModel).CurrentPerson = new Person("Anne", "Aardvark");
    
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Lets say i've got a simple Map which is queried frequently, but only very
Lets say I've got two interchangeable pieces of code and I want to figure
Lets say I've got a table listing car brands or models: Cars : Id
Let's say I've got: Dim los1 as New List(Of String) los1.Add(Some value) Dim los2
Using Delphi 2010, let's say I've got a class declared like this: TMyList =
I'm new to JSF and am wondering if I got things right. Let's say
I'm new to OO PHP. Got some questions. class a { protected function a1()
Lets say I've got two squares and I know their positions, a red and
Let's say I have a class Voucher: public class Voucher { public Guid Id
To keep this simple, lets say I have two tables. The first is called

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.