ObservableCollection не обновляет источник элемента
У меня есть наблюдаемая коллекция, которая заполняется из сетевого потока. Если заполнить OC из конструктора фиктивными данными, он появится в интерфейсе пользователя. Я знаю, что элементы добавляются в коллекцию из сетевого потока, но количество элементов никогда не обновляется в пользовательском интерфейсе.
Моя модель зрения выглядит следующим образом:
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
Я связываю коллекцию манекенов со следующим взглядом.
<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>
6 ответов
Таким образом, существует два типа наблюдаемых коллекций, один в System.Collections.ObjectModel; один в Remotion.Linq.Collections; По-видимому, коллекция Remotion не обновляется должным образом при использовании отдельного потока. Изменено на System.Collections.ObjectModel и теперь все работает нормально.
Вы должны вызвать событие PropertyChanged при обновлении коллекции в своей модели представления, и ваша модель представления должна реализовывать INotifyPropertyChanged
Пользовательский интерфейс не знает, когда ваша коллекция обновляется. Вы должны на самом деле уведомить об этом. Чтобы сделать это, выполните следующие действия:
Внедрить / наследовать от
INotifyPropertyChanged
Скопируйте и вставьте этот код. Я не буду вдаваться в подробности, но это довольно общий код, который можно использовать с любым классом.
public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string PropertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(PropertyName)); } }
Теперь, когда ваш список обновляется, звоните
OnPropertyChanged
метод и передать имя свойства, которое изменилось. (В твоем случаеOnPropertyChanged("Manikins")
)
ObservableCollection обновляет пользовательский интерфейс, когда событие CollectionChanged фактически возникает, когда вы добавляете / удаляете элемент в этой коллекции... если удерживаемая коллекция изменила пользовательский интерфейс, обновляться не будет... я видел, что вы использовали метод Manikins.Add() и на самом деле это странно, что пользовательский интерфейс не обновляется, поэтому сначала проверьте, действительно ли в коллекцию добавлен элемент, во-вторых, убедитесь, что в вашем коде нет ничего, что настраивает всю коллекцию на новую ссылку... Надеюсь, это помогло
Вам нужно добавить элементы в ObservableCollection<>
в потоке пользовательского интерфейса, чтобы перекрасить / обновить элементы управления по мере необходимости.
Вы пытались использовать поток Distacher для синхронного добавления элементов в поток пользовательского интерфейса? Вот что можно попробовать:
Вместо:
Manikins.Add(csvm);
Вы заменяете на:
Dispatcher.BeginInvoke(DispatcherPriority.Normal , new Action(() =>
{
Manikins.Add(csvm);
}
));
Надеюсь это hepls