Можно ли создать элементы управления в отдельном потоке, который можно вернуть в поток пользовательского интерфейса для использования? - PullRequest
0 голосов
/ 22 января 2020

Мой проект устанавливает содержимое TabItems на основе содержимого предоставленного файла XML. Файл XML читается, и содержимое добавляется в TabItem, который может включать TextBlocks, Borders, Buttons, OxyPlots и т. Д.

Это может занять заметное количество времени в зависимости от размера и сложности. файла XML. Оптимально, я хотел бы построить содержимое TabItem в отдельном потоке, а затем вернуть его в поток пользовательского интерфейса для отображения.

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

Есть ли способ изменить владение потоком элементами управления?

1 Ответ

0 голосов
/ 22 января 2020

Добро пожаловать в SO!

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

public class MainViewModel : ViewModelBase
{
    public ObservableCollection<Color> Colors { get; } = new ObservableCollection<Color>();

    public MainViewModel()
    {
        Task.Run(async () =>
        {
            foreach (var color in ColorStructToList())
            {
                await Task.Delay(TimeSpan.FromMilliseconds(10));
                Application.Current.Dispatcher.Invoke(() => this.Colors.Add(color));
            }
        });

    }

    // courtesy https://stackoverflow.com/a/16130999/1177147
    public static List<Color> ColorStructToList()
    {
        return typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
                            .Select(c => (Color)c.GetValue(null, null))
                            .ToList();
    }

}

А вот ItemsControl, который будет создавать элементы, отображающие их по мере их создания, без привязки к основному GUI нить:

<ItemsControl ItemsSource="{Binding Colors}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="10" Height="10" Margin="2" >
                <Rectangle.Fill>
                    <SolidColorBrush Color="{Binding}" />
                </Rectangle.Fill>
            </Rectangle>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
...