For this type of requirement, I did the following:
I first accepted the following as part of my ListBox data template
<StackPanel Width="450"> <TextBlock Text="{Binding text}" Width="450" TextWrapping="Wrap" FontSize="24" Visibility="Collapsed"/> <RichTextBox Width="450" FontSize="24" Foreground="#FFFFFF"/> </StackPanel>
Then in the code behind: The list that I use to bind to the ListBox is defined as follows
public List<Result> results { get { return _results; } set { string x = null; foreach (var item in value) { item.text2 = item.text; if (!item.text.StartsWith("<Section")) if(!item.text.Contains("</Run>")) { String xamlData = null; var regx = new Regex(@query.Trim(), RegexOptions.IgnoreCase); var matcches = regx.Matches(item.text); x += matcches.Count; if (matcches.Count > 0) { var match = @query.Trim(); xamlData = Regex.Replace(item.text, match, "<Run Foreground="Blue" FontWeight=\"ExtraBold\">" + match + "</Run>", RegexOptions.IgnoreCase); } if (xamlData == null) xamlData = item.text; item.text = "<Section xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"><Paragraph>" + xamlData + "</Paragraph></Section>"; } } _results = value; } }
Then, after receiving the search results, add them to the list above, and then set it as ItemsSource for the ListBox.
Now this is a critical part of the ListBox. Add a listbox_SizeChanged event handler as shown below
private void listboxMyTimeline_SizeChanged(object sender, SizeChangedEventArgs e) { for (int i = 0; i < listboxMyTimeline.Items.Count; i++) { ListBoxItem lbi2 = (ListBoxItem)(listboxMyTimeline.ItemContainerGenerator.ContainerFromIndex(i)); if (lbi2 != null) { var ob = FindFirstElementInVisualTree<RichTextBox>(lbi2); var ob2 = FindFirstElementInVisualTree<TextBlock>(lbi2); ob.Xaml = ob2.Text; } else { var itm = listboxMyTimeline.Items.ElementAt(i); lbi2 = (ListBoxItem)(listboxMyTimeline.ItemContainerGenerator.ContainerFromItem(itm)); if (lbi2 != null) { var ob = FindFirstElementInVisualTree<RichTextBox>(lbi2); var ob2 = FindFirstElementInVisualTree<TextBlock>(lbi2); ob.Xaml = ob2.Text; } } } }
Where the FindFirstElementVisualTree method is similar to this
private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject { var count = VisualTreeHelper.GetChildrenCount(parentElement); if (count == 0) return null; for (int i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parentElement, i); if (child != null && child is T) { return (T)child; } else { var result = FindFirstElementInVisualTree<T>(child); if (result != null) return result; } } return null; }
So, I take a hidden text box to which I bind the actual text, the built-in XAML code. This is because you cannot directly bind to RichTextBox or Run elements. Then, in the Size_changed handler, I set this XAMl code to the visible RichTextBox.
I'm not sure how it suits your needs, you may need to make many changes to the above process to make it work for you.
Good luck :)
UPDATE:
Replace the Result class in my code with the Address class in your code.
And replace the definition of your list with your list.
Add an additional property called "xamlCode" to the Address class. (Replace the line item.text2 = item.text with item.xamlCode = item.DisplayName
And the rest should be clear to you.
If in doubt, ask here .