Попытка «пульсировать» обновления DateTime в приложении WPF - PullRequest
0 голосов
/ 27 сентября 2011

Прошу прощения за длинное объяснение.

Я работаю над настольным приложением WPF (показано ниже):

enter image description here

Обычно в списке может быть 0..n элементов состояния процесса (сами элементы представляют собой ListBoxItems, отображаемые с использованием DataTemplate). Недавно я решил, что хочу предоставить представление в формате «истекшее время» (n секунд / минут / часов назад) в качестве альтернативы абсолютному формату DateTime (мм / дд / гггг в формате ЧЧ: мм: сс). Я достиг этого, используя MultiBinding к TextBlock как таковой:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter = "{StaticResource timeElapsedConverter}">
            <Binding 
                Path   = "StatusDateTime"
            />
            <Binding 
                Source = "{StaticResource propertiesHelper}" 
                Path   = "UserOptions.UseElapsedTimeStamps" 
            />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Я избавлю вас от деталей реализации IMultiValueConverter. Вторая привязка относится к вспомогательному классу, который получает настройки отображения метки времени пользователя (то есть они все еще могут видеть абсолютные значения DateTime, если они этого хотят). Свойство StatusDateTime, с которым иначе связан этот TextBlock, не является чем-то особенным; это просто свойство POCO в классе ViewModel, которое запускает OnPropertyChanged, когда установлено.

Это представление синхронизируется с системным бэкэндом каждые (x) секунды. Я хотел бы «пульсировать» временные метки во время синхронизации, чтобы измерения прошедшего времени оставались точными, но если я просто установлю для свойства StatusDateTime его существующее значение, то ничего не произойдет (в примере ниже, он просто скажет «Опубликовано 6 секунд назад ...» до тех пор, пока сам процесс не будет обновлен на стороне сервера или пока приложение не будет загружено во второй раз).

Я пытался добавить IsAsync = "true" в привязку StatusDateTime, как это было предложено в в этом посте , но безрезультатно.

Я также попытался вернуться к обычному связыванию (не мульти) с объявленной простотой Mode = "TwoWay", и это тоже не сработало.

Я знаю, что мог бы просто сдуть список и воссоздать во время синхронизации, но это не выглядит очень элегантно, когда у меня уже есть все данные, которые мне нужны, загруженные в клиент.

Обновление: Я попытался воссоздать эту базовую настройку в окне, и она, кажется, работала очень хорошо. Теперь мне интересно, связано ли это с тем, что целевой элемент управления находится на странице или в части шаблона данных.

Есть мысли? Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Способ, которым я достиг этого в своем приложении на основе MVVM, заключался в том, чтобы на моем ViewModel работал простой таймер, который запускает OnPropertyChanged каждую секунду для свойства, которое я хочу обновлять.Вот пример (в синтаксисе IronPython):

self.displayTimer = System.Timers.Timer(1000) #fire every second
self.displayTimer.Elapsed += self.displayTimer_Tick
self.displayTimer.Start()

def displayTimer_Tick(self, sender, event):
    self.OnPropertyChanged("StatusDateTime")

При этом используется System.Timers.Timer, который выполняет обратный вызов в фоновом потоке ThreadPool, поэтому он не будет мешать диспетчеру.

0 голосов
/ 27 сентября 2011

Хорошо, так что я думаю, что понял это. Я пропустил ключевую деталь, которая быстрее бы указала нам правильное направление: мой DataTemplate поддерживается CollectionViewSource. Если я вызываю метод Refresh () для свойства CollectionViewSource View, отметки времени обновляются, как и ожидалось. Я всегда забываю, что изменение свойств элементов ObservableCollection не обязательно вызывает событие CollectionChanged, которое, таким образом, побуждает CollectionViewSource к обновлению.

Спасибо всем, кто ответил!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...