joshwl2003
joshwl2003

Reputation: 463

ObservableCollection not updating item source

I have an observable collection which is being populated from a networking thread. If a populate the OC from the constructor with dummy data it shows up on the UI. I know that the items are being added to the collection from the network thread but the Items count never updates on the UI.

My view model is as follows:

public class ManikinStatusViewModel : DiViewModelBase
{
    private readonly ICommunicationService manikinCommunicationService;

    #region Properties
    public ObservableCollection<CasualtyStatusViewModel> Manikins { get; private set; }
    #endregion

    public ManikinStatusViewModel()
    {
        Manikins = new ObservableCollection<CasualtyStatusViewModel>();

        uow = UnitOfWorkFactory.Instance.CreateRunScenarioUnitOfWork(false);

        AccelermeterPacketData apd = new AccelermeterPacketData(56, 57, 58);

        manikinCommunicationService = new TestingCommunicationService(LoadAnalogSensorData(), apd);
        manikinCommunicationService.ManikinDataReceived += ManikinCommunicationService_ManikinDataReceived;

    }

    #region Events
    private void ManikinCommunicationService_ManikinDataReceived(object sender, ManikinDataReceivedEventArgs e)
    {
        if (e.ManiknDataPacket != null)
        {
            var manikin = Manikins.ToList().Find(m => m.ManikinId == e.ManiknDataPacket.SerialNumber);

            if (manikin == null)
            {
                Debug.WriteLine("Creating manikin with serial number: " + e.ManiknDataPacket.SerialNumber);

                CasualtyStatusViewModel csvm = new CasualtyStatusViewModel(e.ManiknDataPacket.SerialNumber);
                Manikins.Add(csvm);

                manikin = csvm;

                Debug.WriteLine("manikin count is: " + Manikins.Count());

            }

            manikin.UpdateManikinStatus(e.ManiknDataPacket);
        }
    }

    #endregion

I am binding the manikins collection to the following view.

   <TabControl Grid.Row="1" ItemsSource="{Binding Manikins}" Name="ManikinsTabControl">
        <TabControl.Resources>
            <Style TargetType="TabItem">
                <Setter Property="Header" Value="Casualty"></Setter>
                <Setter Property="ContentTemplate" Value="{StaticResource CasualtyTemplate}"></Setter>
            </Style>
        </TabControl.Resources>
    </TabControl>

Upvotes: 1

Views: 2538

Answers (6)

joshwl2003
joshwl2003

Reputation: 463

So there are 2 types of observable collections one in System.Collections.ObjectModel; one in Remotion.Linq.Collections; Apparently the Remotion collection does not update properly when being used a separate thread. Changed to the System.Collections.ObjectModel and all appears to be working fine now.

Upvotes: 1

Ibrahim Abdelkareem
Ibrahim Abdelkareem

Reputation: 973

ObservableCollection updating the UI when the event CollectionChanged is raised in fact when you Add/Delete an item within this collection ... if the hold Collection changed the UI wont be updated ... i've seen you used Manikins.Add() method and actually this is weird that UI isn't updated so check first if there is really item added to the collection, second make sure that there isn't anything in your code setting the whole collection to a new reference ... Hope that helped

Upvotes: 0

Arsalan Ahmad
Arsalan Ahmad

Reputation: 688

The UI doesn't know when your collection is being updated. You have to actually notify it. To do that, here are the steps you need to follow:

  1. Implement/inherit from INotifyPropertyChanged

  2. Copy paste this code. I won't go into the details here but this is pretty generic code that can be used with any class.

    public event PropertyChangedEventHandler PropertyChanged;
    
    protected virtual void OnPropertyChanged(string PropertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
    
  3. Now whenever your list is updated, call the OnPropertyChanged method and pass the name of the property that changed. (In your case OnPropertyChanged("Manikins"))

Upvotes: 2

potehin143
potehin143

Reputation: 531

You have to rise PropertyChanged event on updating collection in your viewmodel and your viewmodel must implement INotifyPropertyChanged

Upvotes: 2

jhontarrede
jhontarrede

Reputation: 124

Did you tried using the Distacher thread to add items synchronously on the UI thread ? Here is is something to try :

Instead of :

Manikins.Add(csvm);

You replace with :

Dispatcher.BeginInvoke(DispatcherPriority.Normal , new Action(() => 
{ 
    Manikins.Add(csvm); 
} 
));

Hope this hepls

Upvotes: 0

Rowland Shaw
Rowland Shaw

Reputation: 38130

You need the items to be added to the ObservableCollection<> in the UI thread for it to repaint/update controls as required.

Upvotes: 0

Related Questions