Note that there are some explanatory texts on larger screens.

plurals
  1. POComboBox ItemsSource changed => SelectedItem is ruined
    primarykey
    data
    text
    <p>Ok, this has been bugging me for a while now. And I wonder how others handle the following case:</p> <pre><code>&lt;ComboBox ItemsSource="{Binding MyItems}" SelectedItem="{Binding SelectedItem}"/&gt; </code></pre> <p>The DataContext object's code:</p> <pre><code>public ObservableCollection&lt;MyItem&gt; MyItems { get; set; } public MyItem SelectedItem { get; set; } public void RefreshMyItems() { MyItems.Clear(); foreach(var myItem in LoadItems()) MyItems.Add(myItem); } public class MyItem { public int Id { get; set; } public override bool Equals(object obj) { return this.Id == ((MyItem)obj).Id; } } </code></pre> <p>Obviously when the <code>RefreshMyItems()</code> method is called the combo box receives the Collection Changed events, updates its items and does not find the SelectedItem in the refreshed collection => sets the SelectedItem to <code>null</code>. But I would need the combo box to use <code>Equals</code> method to select the correct item in the new collection.</p> <p>In other words - the ItemsSource collection still contains the correct <code>MyItem</code>, but it is a <code>new</code> object. And I want the combo box to use something like <code>Equals</code> to select it automatically (this is made even harder because first the source collection calls <code>Clear()</code> which resets the collection and already at that point the SelectedItem is set to <code>null</code>).</p> <p><strong>UPDATE 2</strong> Before copy-pasting the code below please note that it is far from perfection! And note that it does not bind two ways by default.</p> <p><strong>UPDATE</strong> Just in case someone has the same problem (an attached property as proposed by Pavlo Glazkov in his answer):</p> <pre><code>public static class CBSelectedItem { public static object GetSelectedItem(DependencyObject obj) { return (object)obj.GetValue(SelectedItemProperty); } public static void SetSelectedItem(DependencyObject obj, object value) { obj.SetValue(SelectedItemProperty, value); } // Using a DependencyProperty as the backing store for SelectedIte. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(CBSelectedItem), new UIPropertyMetadata(null, SelectedItemChanged)); private static List&lt;WeakReference&gt; ComboBoxes = new List&lt;WeakReference&gt;(); private static void SelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ComboBox cb = (ComboBox) d; // Set the selected item of the ComboBox since the value changed if (cb.SelectedItem != e.NewValue) cb.SelectedItem = e.NewValue; // If we already handled this ComboBox - return if(ComboBoxes.SingleOrDefault(o =&gt; o.Target == cb) != null) return; // Check if the ItemsSource supports notifications if(cb.ItemsSource is INotifyCollectionChanged) { // Add ComboBox to the list of handled combo boxes so we do not handle it again in the future ComboBoxes.Add(new WeakReference(cb)); // When the ItemsSource collection changes we set the SelectedItem to correct value (using Equals) ((INotifyCollectionChanged) cb.ItemsSource).CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e2) { var collection = (IEnumerable&lt;object&gt;) sender; cb.SelectedItem = collection.SingleOrDefault(o =&gt; o.Equals(GetSelectedItem(cb))); }; // If the user has selected some new value in the combo box - update the attached property too cb.SelectionChanged += delegate(object sender, SelectionChangedEventArgs e3) { // We only want to handle cases that actually change the selection if(e3.AddedItems.Count == 1) { SetSelectedItem((DependencyObject)sender, e3.AddedItems[0]); } }; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload