none
DataBinding:ComboBox doesn't refresh on Collection change - How do I notify the Target of a collection change

    Question

  • I have a ComboBox which binds to a volatile collection.

    When the collection is changed, the ComboBox (drop-down) list isn't refreshed if it has already been dropped down by the user.

    If the user does not drop-down the list before the collection change, then it does a fresh read on the source and gets the correct data.

    I'm wondering if there is a notification event that I need to raise other than the standard PropertyChanged to force the ComboBox to refresh.

    Note: The collection object has no access or awareness of the control (as it shoudl be) so it can't be done manually.

    Thanks

    Nik

     

     

     

    Friday, September 22, 2006 5:27 PM

All replies

  • I've tested the ComboBox, It does refresh its visuals when the underlying data bound collection changed, for instance:

    <Window x:Class="DynamicComboBox.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DynamicComboBox" 
        Title="DynamicComboBox" Height="300" Width="300"
        >
      <Window.Resources>
        <ObjectDataProvider ObjectType="{x:Type local:DynamicCollection}" x:Key="dataObject"/>
      </Window.Resources>
        <Grid>
          <ComboBox Width="200" Height="40" ItemsSource="{Binding Source={StaticResource dataObject}}"/>
        </Grid>
    </Window>


    public partial class Window1 : System.Windows.Window
        {
     
            public Window1()
            {
                InitializeComponent();
            }
        }
     
        public class DynamicCollection : ObservableCollection<String>
        {
            private DispatcherTimer timer;
            private Int32 currenIndex = 0;
            private String item;
            public DynamicCollection()
            {
                timer = new DispatcherTimer(DispatcherPriority.Background, Application.Current.Dispatcher);
                timer.Interval = TimeSpan.FromMilliseconds(500);
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }
     
            private void timer_Tick(object sender, EventArgs e)
            {
                item = "Item " + currenIndex.ToString();
                this.Add(item);
                currenIndex++;
            }
        }


    when you open the dropdown, you will see the amount of items contained in it increases as expected.

    Sheva


    Friday, September 22, 2006 6:04 PM
  • If you're saying you have a custom collection class, then you need to implement INotifyCollectionChanged on that class in order for WPF databinding to watch for changes to it automatically.

    HTH,
    Drew

    Friday, September 22, 2006 7:14 PM
    Moderator
  • Yes, that works, but I have a different design to contend with. 

    My ComboBox is bound to a ReadOnlyCollection Property on an object.

    I converted this property to ObservableCollection, but changes to the underlying Collection are ignored, presumably because no CollectionChanged notification is fired.

     

     

     

     

     

     

     

    Friday, September 22, 2006 7:57 PM
  • Its a custom class that implements a property that is of type ObservableCollection.

    Does that mean its a "Custom Collection Class" ?

    Friday, September 22, 2006 8:17 PM
  • Is the property exposed as an ObservableCollection? You said earlier that it was a ReadOnly collection. How is the binding between the combobox and your collection property made? Inquiring minds want to know

    Friday, September 22, 2006 8:47 PM
    Moderator
  • From previous post

        "I converted this property to an ObservableCollection" - wasn't highlighted.

    I went ahead and implemented the INotifyCollectionChange manually and I'm seeing the most bizarre thing.

    When another object registers for the event

       MyCollection.CollectionChange += MyOtherClass.CollectionChangeHandler;

    Nothing happens, the event remains null, no errors, no exceptions, just no-op - obviously the registering object never gets the notification.

    ================

    To answer your question:

    Resources

          <src:ItemsSourceBinder SettingName="TimingMode" x:Key="AvailableTimingModesBinder"/>
          <ObjectDataProvider ObjectInstance="{StaticResource AvailableTimingModesBinder}" x:Key="AvailableTimingModes"/>

    Page Xaml

        <ComboBox Name="TimingModeCombo" Height="21" Margin="20,20,20,20" VerticalAlignment="Top">
          <ComboBox.ItemsSource>
            <Binding Path="BinderHook" Source="{StaticResource AvailableTimingModes}" />
          </ComboBox.ItemsSource>
        </ComboBox>

    However, I have an unusual implementation because the Object that supports the BinderHook property is just a connector object, it actual binds the ComboBox.ItemSource explcitly to the source object in code (see below) at the end of the page load and then gets out of the way.

                NewBinding = new Binding("Values");
                NewBinding.Mode = BindingMode.OneWay;
                NewBinding.Source = _Setting;

                BindingOperations.SetBinding(_Element, _DependencyProperty, NewBinding);

    Note: I walk the tree at load time to determine the _Element and the _DependencyProperty values, _Setting is the object that I ultimately bind to that exposes a Values property of type ObservableCollection.

    I know this sounds convoluded, but the binding is correct and the combo properly displays the members of the collection.

    Hey Mike, just realized it was you. Funny, you know all this already.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    Friday, September 22, 2006 9:12 PM
  • Hey Sheva, I was messing around with the sample that you provided and noticed that you aren't binding to a property, but to an entire ObservableCollection object.

    I'm wondering if that is why I'm not seeing the behavior I want.

    Thoughts?

     

    Wednesday, September 27, 2006 6:40 PM
  • Better late than never! I realise this is quite an old thread, but I have just encountered this problem and found what I think may be the solution.

    In my case, although my ComboBox's ItemsSource was bound to an ObservableCollection, and the elements in the collection were of a type which implemented INotifyPropertyChanged, the symptoms I experienced were exactly as described in your original post.

    What I hadn't done, though, was to set the DisplayMemberPath property of the ComboBox, so that it was using ToString to display each item. After I set DisplayMemberPath="Name",  any change to the Name of a source item was immediately reflected in the ComboBox display.

     

    Friday, September 09, 2011 9:54 AM