Работа с данными в текстовом блоке в Silverlight / WP7

Я использую Silverlight на Windows Phone 7.

Я хочу отобразить первую часть некоторого текста в TextBlock жирным шрифтом, а остальное – в обычном шрифте. Полный текст должен быть завершен. Я хочу, чтобы полужирная часть содержала текст из одного свойства в моей модели ViewModel и простой текст, содержащий текст из другого свойства.

TextBlock определен в DataTemplate, связанном с LongListSelector.

Моя первоначальная попытка:

      

Это не удается во время выполнения с эффектно бесполезным «AG_E_RUNTIME_MANAGED_UNKNOWN_ERROR». Это известная проблема, поскольку элемент Run не является элементом FrameworkElement и не может быть привязан.

Моя следующая попытка состояла в том, чтобы поставить заполнители на место, а затем обновить их в коде:

   Placeholder1 Placeholder2   

В коде-позади (да, я в отчаянии!):

 private void TextBlockLoaded(object sender, RoutedEventArgs e) { var textBlock = (TextBlock)sender; var viewModel = (ViewModel)textBlock.DataContext; var prop1Run = (Run)textBlock.Inlines[0]; var prop2Run = (Run)textBlock.Inlines[1]; prop1Run.Text = viewModel.Property1; prop2Run.Text = viewModel.Property2; } 

Это, похоже, сработало, но поскольку я использую LongListSelector, хотя элементы перерабатываются, обработчик события Loaded codebehind не повторно инициализирует Runs, поэтому очень быстро отображается неправильный текст …

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

Любая помощь ценится!

Наконец я нашел решение, которое работает для меня.

Как я упоминаю в комментарии, подход Пола Стовелла не сработает.

Вместо этого я использовал аналогичный подход для добавления прикрепленного свойства к TextBlock, связанного с DataContext TextBlock и прикрепленных свойств в прогонах, с указанием свойств ViewModel, к которым они должны привязываться:

       

Затем в моем добавленном событии свойства TextBox Target (datacontext) я обновляю Runs и подписываюсь, чтобы получать уведомления об изменениях свойств TargetBox Target. Когда свойство TextBox Target изменяется, я соответствующим образом обновлял любой связанный текст Run.

 public static class BindableRuns { private static readonly Dictionary Handlers = new Dictionary(); private static void TargetPropertyPropertyChanged( DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { if(!(dependencyObject is TextBlock)) return; var textBlock = (TextBlock)dependencyObject; AddHandler(e.NewValue as INotifyPropertyChanged, textBlock); RemoveHandler(e.OldValue as INotifyPropertyChanged); InitializeRuns(textBlock, e.NewValue); } private static void AddHandler(INotifyPropertyChanged dataContext, TextBlock textBlock) { if (dataContext == null) return; var propertyChangedHandler = new PropertyChangedHandler(textBlock); dataContext.PropertyChanged += propertyChangedHandler.PropertyChanged; Handlers[dataContext] = propertyChangedHandler; } private static void RemoveHandler(INotifyPropertyChanged dataContext) { if (dataContext == null || !Handlers.ContainsKey(dataContext)) return; dataContext.PropertyChanged -= Handlers[dataContext].PropertyChanged; Handlers.Remove(dataContext); } private static void InitializeRuns(TextBlock textBlock, object dataContext) { if (dataContext == null) return; var runs = from run in textBlock.Inlines.OfType() let propertyName = (string)run.GetValue(TargetProperty) where propertyName != null select new { Run = run, PropertyName = propertyName }; foreach (var run in runs) { var property = dataContext.GetType().GetProperty(run.PropertyName); run.Run.Text = (string)property.GetValue(dataContext, null); } } private class PropertyChangedHandler { private readonly TextBlock _textBlock; public PropertyChangedHandler(TextBlock textBlock) { _textBlock = textBlock; } public void PropertyChanged(object sender, PropertyChangedEventArgs propertyChangedArgs) { var propertyName = propertyChangedArgs.PropertyName; var run = _textBlock.Inlines.OfType() .Where(r => (string) r.GetValue(TargetProperty) == propertyName) .SingleOrDefault(); if(run == null) return; var property = sender.GetType().GetProperty(propertyName); run.Text = (string)property.GetValue(sender, null); } } public static object GetTarget(DependencyObject obj) { return obj.GetValue(TargetProperty); } public static void SetTarget(DependencyObject obj, object value) { obj.SetValue(TargetProperty, value); } public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached("Target", typeof(object), typeof(BindableRuns), new PropertyMetadata(null, TargetPropertyPropertyChanged)); } 

Я предлагаю вам попробовать BindableRun . Я использовал его только в WPF, но я не понимаю, почему он не будет работать в Silverlight.

  • Как программно установить выбранный элемент Panorama в WP7
  • "UpdateSourceTrigger = PropertyChanged" эквивалент для Windows Phone 7 TextBox
  • Закройте приложение Windows Phone 7
  • Как инициировать событие при изменении значения переменной?
  • Как получить версию приложения в Windows Phone?
  • Поддержка локальной базы данных Sql для телефона Windows 7
  • Как увеличить или уменьшить масштаб изображений в WP7?
  • ASCIIEncoding В Windows Phone 7
  • Закройте приложение WP7 программно?
  • Преобразование изображения в base64
  • Windows Phone 7 Browser - выключите серое затенение при нажатии ссылок
  • Давайте будем гением компьютера.