Мое Приложение WPF получает поток сообщений от серверной службы, что я должен отобразиться в UI. Эти сообщения значительно различаются, и я хочу иметь другую визуальную разметку (форматы строки, цвета, Шрифты, значки, безотносительно и т.д.) для каждого сообщения.
Я надеялся просто смочь создать встроенное (Выполненный, TextBlock, Курсив и т.д.) для каждого сообщения затем так или иначе помещает их всех в a ObservableCollection<>
и использование его волшебство Привязки данных WPF на моем TextBlock. Встраивает в UI. Я не мог найти, как сделать это, действительно ли это возможно?
Это невозможно, так как свойство TextBlock.Inlines
не является свойством зависимости. Только зависимые свойства могут быть объектом привязки данных.
В зависимости от ваших требований к макету, вы можете сделать это, используя ItemsControl
, с его ItemsPanel
, установленным в WrapPanel
и его ItemsSource
, установленным в вашей коллекции. (Здесь могут понадобиться некоторые эксперименты, так как Inline
не является UIElement
, поэтому его рендеринг по умолчанию, скорее всего, будет осуществляться с помощью ToString()
, а не с помощью отображения. )
В качестве альтернативы, вам может понадобиться построить новый элемент управления, например, MultipartTextBlock
, со свойством PartsSource
и TextBlock
в качестве шаблона по умолчанию. При установке источника запчастей PartsSource
к устройству управления будет прикреплен обработчик события CollectionChanged
(напрямую или через CollectionChangedEventManager), а также будет обновлен текстовый блок TextBlock. Соединяет коллекцию
с кодом, так как изменилась коллекция PartsSource
.
В любом случае, если Ваш код генерирует элементы Inline
непосредственно (так как Inline
не может быть использован в двух местах одновременно), может потребоваться осторожность. В качестве альтернативы Вы можете рассмотреть возможность разоблачения абстрактной модели текста, шрифта и т.д. (т.е. модель вида) и создать фактические объекты Inline
с помощью DataTemplate
. Это также может улучшить тестируемость, но, очевидно, добавляет сложности и усилий.
Если я правильно понял ваше требование, вы можете вручную проверить приходящие сообщения и для каждого сообщения вы можете добавить элемент в свойство TextBlock.Inlines. Для этого не потребуется никаких DataBinding. Я сделал это со следующим:
public string MyBindingPath
{
get { return (string)GetValue(MyBindingPathProperty); }
set { SetValue(MyBindingPathProperty, value); }
}
// Using a DependencyProperty as the backing store for MyBindingPath. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyBindingPathProperty =
DependencyProperty.Register("MyBindingPath", typeof(string), typeof(Window2), new UIPropertyMetadata(null, OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
(sender as Window2).textBlock.Inlines.Add(new Run(e.NewValue.ToString()));
}
В версии 4 WPF вы сможете связать с объектом Run, что может решить вашу проблему.
Я решил эту проблему в прошлом, переопределив ItemsControl и отобразив текст как элементы в ItemsControl. Посмотрите на некоторые учебники, которые Dr. WPF сделал по таким вещам: http://www.drwpf.com