Привязка WPF не работает при использовании другой модели данных ⇐ C#
-
Гость
Привязка WPF не работает при использовании другой модели данных
Я создаю приложение, которое отслеживает несколько серверов трассировки на удаленных компьютерах и отображает обработанные данные в пользовательском интерфейсе. Когда я использую симулятор, генерирующий данные, все работает так, как ожидалось. Проблема в том, что пользовательский интерфейс не обновляется при использовании фактической модели данных. Иногда он обновляется один раз после запуска, иногда никогда. ViewModel нетронута, данные правильно обработаны и доступны. Это влияет на все элементы управления, использующие привязку в XAML. Другие элементы управления, которые обновляются в коде, работают должным образом. Все модели представления правильно реализуют INotifyPropertyChanged.
См. следующий пример:
Пользовательский элемент управления TimeStrip
В этом элементе управления TimeStrip текстовое поле и строка должны перемещаться вправо со временем.
XAML UserControl:
//.. //... Серые прямоугольники (TimeSlot) обновляются с помощью Grid_LayoutUpdated, который устанавливает градиент фона в соответствии с текущим временем:
Код
private void Grid_LayoutUpdated (отправитель объекта, EventArgs e) { Контекст MainViewModel = DataContext как MainViewModel; context.UiStuff.GridWidth = TimeCanvas.ActualWidth; DateTime dt = context.UiStuff.CurrentTime; int currentHour = dt.AddHours(-6).Hour; двойной currentHourPart = dt.Minute / 60d; for (int i = 0; i currentTimeString; установить {currenTimeString = значение; OnPropertyChanged();} } } Как видно на скриншоте, привязки обновились только один раз после запуска (9:51). TimeSlots отображаются правильно (сейчас 10:30).
Как уже упоминалось, все это работает при использовании симулятора. Единственное отличие заключается в объекте TraceCommunication, который контролирует удаленную систему. ViewModel подписывается на событие MessageReceived и соответствующим образом устанавливает элементы пользовательского интерфейса.
публичный класс TraceCommunication { внутренний делегат void TraceEventHandler (значение DataRow); внутреннее событие TraceEventHandler MessageReceived; частный TraceEngineIntf TraceEngine; частная строка _Ip; частная строка _Порт; общественная Трассировка() { //... } внутренний bool StartConnection (строка ip, строка порта) { _Ip = IP; _Порт = порт; bool успех = правда; если (!ip.Contains(".")) { TraceSimulator Sim = новый TraceSimulator(ip); Sim.MessageReceived += FireEventIfRelevant; Sim.StartTracing(); } еще { TraceEngine = новый TraceEngineIntf (); трассировкаEngine.ConnectedChanged += Trace_ConnectedChanged; трассировкаEngine.MessageReceived += FireEventIfRelevant; успех = трассировкаEngine.SetHost(_Ip, _Port); } вернуть успех; } частная пустота FireEventIfRelevant (строка DataRow) { if (!TraceFilter.IsRelevant(row)) return; MessageReceived?.Invoke(строка); } частный void Trace_ConnectedChanged (отправитель объекта, EventArgs e) { TraceEngine = отправитель как TraceEngineIntf; если (traceEngine.Connected) { трассировкаEngine.StartRead(); } еще { Соединять(); } } } В обоих случаях данные принимаются и обрабатываются корректно. События запускаются, а затем правильно обрабатываются в ViewModel. Но пользовательский интерфейс реагирует только при использовании симулятора. Так было не всегда. Я начал использовать только настоящую вещь, которая работала нормально. Позже я внедрил симулятор, когда мне потребовалось больше данных для разработки.
У меня нет идей, что может вызвать такое поведение. Кто-нибудь знает, что происходит, или может подсказать, что проверить дальше?
Спасибо!
Я создаю приложение, которое отслеживает несколько серверов трассировки на удаленных компьютерах и отображает обработанные данные в пользовательском интерфейсе. Когда я использую симулятор, генерирующий данные, все работает так, как ожидалось. Проблема в том, что пользовательский интерфейс не обновляется при использовании фактической модели данных. Иногда он обновляется один раз после запуска, иногда никогда. ViewModel нетронута, данные правильно обработаны и доступны. Это влияет на все элементы управления, использующие привязку в XAML. Другие элементы управления, которые обновляются в коде, работают должным образом. Все модели представления правильно реализуют INotifyPropertyChanged.
См. следующий пример:
Пользовательский элемент управления TimeStrip
В этом элементе управления TimeStrip текстовое поле и строка должны перемещаться вправо со временем.
XAML UserControl:
//.. //... Серые прямоугольники (TimeSlot) обновляются с помощью Grid_LayoutUpdated, который устанавливает градиент фона в соответствии с текущим временем:
Код
private void Grid_LayoutUpdated (отправитель объекта, EventArgs e) { Контекст MainViewModel = DataContext как MainViewModel; context.UiStuff.GridWidth = TimeCanvas.ActualWidth; DateTime dt = context.UiStuff.CurrentTime; int currentHour = dt.AddHours(-6).Hour; двойной currentHourPart = dt.Minute / 60d; for (int i = 0; i currentTimeString; установить {currenTimeString = значение; OnPropertyChanged();} } } Как видно на скриншоте, привязки обновились только один раз после запуска (9:51). TimeSlots отображаются правильно (сейчас 10:30).
Как уже упоминалось, все это работает при использовании симулятора. Единственное отличие заключается в объекте TraceCommunication, который контролирует удаленную систему. ViewModel подписывается на событие MessageReceived и соответствующим образом устанавливает элементы пользовательского интерфейса.
публичный класс TraceCommunication { внутренний делегат void TraceEventHandler (значение DataRow); внутреннее событие TraceEventHandler MessageReceived; частный TraceEngineIntf TraceEngine; частная строка _Ip; частная строка _Порт; общественная Трассировка() { //... } внутренний bool StartConnection (строка ip, строка порта) { _Ip = IP; _Порт = порт; bool успех = правда; если (!ip.Contains(".")) { TraceSimulator Sim = новый TraceSimulator(ip); Sim.MessageReceived += FireEventIfRelevant; Sim.StartTracing(); } еще { TraceEngine = новый TraceEngineIntf (); трассировкаEngine.ConnectedChanged += Trace_ConnectedChanged; трассировкаEngine.MessageReceived += FireEventIfRelevant; успех = трассировкаEngine.SetHost(_Ip, _Port); } вернуть успех; } частная пустота FireEventIfRelevant (строка DataRow) { if (!TraceFilter.IsRelevant(row)) return; MessageReceived?.Invoke(строка); } частный void Trace_ConnectedChanged (отправитель объекта, EventArgs e) { TraceEngine = отправитель как TraceEngineIntf; если (traceEngine.Connected) { трассировкаEngine.StartRead(); } еще { Соединять(); } } } В обоих случаях данные принимаются и обрабатываются корректно. События запускаются, а затем правильно обрабатываются в ViewModel. Но пользовательский интерфейс реагирует только при использовании симулятора. Так было не всегда. Я начал использовать только настоящую вещь, которая работала нормально. Позже я внедрил симулятор, когда мне потребовалось больше данных для разработки.
У меня нет идей, что может вызвать такое поведение. Кто-нибудь знает, что происходит, или может подсказать, что проверить дальше?
Спасибо!
Мобильная версия