Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Ok I have found the answer (using a lot of Reflector to figure out how the ComboBox works).</p> <p>The problem exists when the ItemSource is set after the SelectedItem is set. When this happens the Combobx sees it as a complete Reset of the selection and clears the SelectedItem/SelectedIndex. You can see this here in the System.Windows.Controls.Primitives.Selector (the base class for the ComboBox):</p> <pre><code>protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) { base.OnItemsChanged(e); int selectedIndex = this.SelectedIndex; bool flag = this.IsInit &amp;&amp; this._initializingData.IsIndexSet; switch (e.Action) { case NotifyCollectionChangedAction.Add: if (!this.AddedWithSelectionSet(e.NewStartingIndex, e.NewStartingIndex + e.NewItems.Count)) { if ((e.NewStartingIndex &lt;= selectedIndex) &amp;&amp; !flag) { this._processingSelectionPropertyChange = true; this.SelectedIndex += e.NewItems.Count; this._processingSelectionPropertyChange = false; } if (e.NewStartingIndex &gt; this._focusedIndex) { return; } this.SetFocusedItem(this._focusedIndex + e.NewItems.Count, false); } return; case NotifyCollectionChangedAction.Remove: if (((e.OldStartingIndex &gt; selectedIndex) || (selectedIndex &gt;= (e.OldStartingIndex + e.OldItems.Count))) &amp;&amp; (e.OldStartingIndex &lt; selectedIndex)) { this._processingSelectionPropertyChange = true; this.SelectedIndex -= e.OldItems.Count; this._processingSelectionPropertyChange = false; } if ((e.OldStartingIndex &lt;= this._focusedIndex) &amp;&amp; (this._focusedIndex &lt; (e.OldStartingIndex + e.OldItems.Count))) { this.SetFocusedItem(-1, false); return; } if (e.OldStartingIndex &lt; selectedIndex) { this.SetFocusedItem(this._focusedIndex - e.OldItems.Count, false); } return; case NotifyCollectionChangedAction.Replace: if (!this.AddedWithSelectionSet(e.NewStartingIndex, e.NewStartingIndex + e.NewItems.Count)) { if ((e.OldStartingIndex &lt;= selectedIndex) &amp;&amp; (selectedIndex &lt; (e.OldStartingIndex + e.OldItems.Count))) { this.SelectedIndex = -1; } if ((e.OldStartingIndex &gt; this._focusedIndex) || (this._focusedIndex &gt;= (e.OldStartingIndex + e.OldItems.Count))) { return; } this.SetFocusedItem(-1, false); } return; case NotifyCollectionChangedAction.Reset: if (!this.AddedWithSelectionSet(0, base.Items.Count) &amp;&amp; !flag) { this.SelectedIndex = -1; this.SetFocusedItem(-1, false); } return; } throw new InvalidOperationException(); } </code></pre> <p>Note the last case - the reset...When you load a new ItemSource you end up here and any SelectedItem/SelectedIndex gets blown away?!?!</p> <p>Well the solution was pretty simple in the end. i just subclassed the errant ComboBox and provided and override for this method as follows. Though I did have to add a :</p> <pre><code>public class FixedComboBox : ComboBox { public FixedComboBox() : base() { // This is here to sync the dep properties (OnSelectedItemChanged is private is the base class - thanks M$) base.SelectionChanged += (s, e) =&gt; { FixedSelectedItem = SelectedItem; }; } // need to add a safe dependency property here to bind to - this will store off the "requested selectedItem" // this whole this is a kludgy wrapper because the OnSelectedItemChanged is private in the base class public readonly static DependencyProperty FixedSelectedItemProperty = DependencyProperty.Register("FixedSelectedItem", typeof(object), typeof(FixedComboBox), new PropertyMetadata(null, new PropertyChangedCallback(FixedSelectedItemPropertyChanged))); private static void FixedSelectedItemPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { FixedComboBox fcb = obj as FixedComboBox; fcb.mLastSelection = e.NewValue; fcb.SelectedItem = e.NewValue; } public object FixedSelectedItem { get { return GetValue(FixedSelectedItemProperty); } set { SetValue(FixedSelectedItemProperty, value);} } protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { base.OnItemsChanged(e); if (-1 == SelectedIndex) { // if after the base class is called, there is no selection, try if (null != mLastSelection &amp;&amp; Items.Contains(mLastSelection)) SelectedItem = mLastSelection; } } protected object mLastSelection = null; } </code></pre> <p>All that this does is (a) save off the old SelectedItem and then (b) check that if after the ItemsChanged, if we have no selection made and the old SelectedItem exists in the new list...well...Selected It!</p>
 

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