Я пытаюсь заполнить ListView набором ObservableCollection SearchResult
, содержащим ObservableCollection<Inline>
.Моя (упрощенная) структура данных:
public class SearchResult
{
public static ObservableCollection<Inline> FormatString(string s)
{
ObservableCollection<Inline> inlineList = new ObservableCollection<Inline>
{
new Run("a"),
new Run("b") { FontWeight = FontWeights.Bold },
new Run("c")
};
return inlineList;
}
public ObservableCollection<Inline> Formatted { get; set; }
public string Raw { get; set; }
}
Содержит ObservableCollection<Inline>
, потому что эти результаты поиска будут отображаться с пользовательским BindableTextBlock
, который поддерживает форматированный текст:
public class BindableTextBlock : TextBlock
{
public ObservableCollection<Inline> InlineList
{
get { return (ObservableCollection<Inline>)GetValue(InlineListProperty); }
set { SetValue(InlineListProperty, value); }
}
public static readonly DependencyProperty InlineListProperty = DependencyProperty.Register("InlineList", typeof(ObservableCollection<Inline>), typeof(BindableTextBlock), new UIPropertyMetadata(null, OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
BindableTextBlock textBlock = (BindableTextBlock)sender;
textBlock.Inlines.Clear();
textBlock.Inlines.AddRange((ObservableCollection<Inline>)e.NewValue);
}
}
Однакопри заполнении ListView
<ListView Name="allSearchResultsListView">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<local:BindableTextBlock InlineList="{Binding Formatted}" />
<TextBlock Text="{Binding Raw}" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
следующим BackgroundWorker
public partial class MainWindow : Window
{
private readonly BackgroundWorker worker = new BackgroundWorker();
ObservableCollection<SearchResult> searchResults = new ObservableCollection<SearchResult>();
public MainWindow()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
for (long i = 0; i < 1000; i++)
{
searchResults.Add(new SearchResult()
{
Formatted = SearchResult.FormatString("a*b*c"),
Raw = "abc"
});
}
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
allSearchResultsListView.ItemsSource = searchResults;
}
}
программа аварийно завершает работу с
Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll
Inner Exception: The calling thread cannot access this object because a different thread owns it
Проблема в том, что внутри фонового рабочего элемента создаются элементы (Inline
), которые не принадлежат потоку пользовательского интерфейса.При назначении ItemsSource после того, как работник завершил работу, возникает исключение.
Подобные вопросы, похоже, задавались много, но я не смог найти ничего для своего конкретного случая.
Любая помощьоценили!