У меня очень сложный UserControl, который необходимо создать во время выполнения. Это создание замораживает графический интерфейс около 5 секунд (что неприемлемо).Создайте комплекс UserControl во время выполнения без замораживания GUI
Я пытался переместить эту операцию в Фоновой работнику и в конечном итоге с этим Exception:
Вызывающий поток должен быть STA, так как многие компоненты пользовательского интерфейса требует этого.
Я знаю, что я не могу использовать поток MTA для создания элемента UserControl/UI. Я попытался использовать комбинацию BackgroundWorker и Dispatcher, но это не сработало.
Сначала попробуйте
private void LetsGo()
{
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
DispatcherOperation dispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(new Action(this.GenerateControlAsync), DispatcherPriority.Background);
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
// Cancelled
}
else if (e.Error != null)
{
//Exception Thrown
}
else
{
//Completed
}
}
private void GenerateControlAsync() {
this.Control = new TimeConsumingUserControl();
}
Код выше не работает, метод this.GenerateControlAsync не выполняется.
Второй попробовать
private async void GenerateControl()
{
this.Control = await Dispatcher.CurrentDispatcher.InvokeAsync<UserControl>(this.GenerateControlAsync);
}
private UserControl GenerateControlAsync()
{
return new TimeConsumingUserControl();
}
этот пример работает, но он держит замораживание GUI поток.
Я использую WPF и .net Framework 4.5.
Обратите внимание, что метод GenerateControlAsync() не просто создает экземпляр UserControl, .
Чтобы ответить на вопрос @HighCore «s: На самом деле XAML кодекс UserControl преобразуется из XML-файлов с помощью XSLT и Codebehind генерируется с использованием CodeDOM. Все вещи должны быть скомпилированы и завернуты в сборку. Я использую assembly.CreateInstance(), чтобы получить экземпляр UserControl. Эта строка выбрасывает исключение. В моем графическом интерфейсе у меня есть ContentControl, который имеет привязку к UserControl в моей ViewModel. Данные для генерации, такие как xml-файлы, которые необходимо преобразовать, извлекаются из веб-службы.
Вот почему выполнение этого метода занимает немного больше времени, чем кто-то может ожидать.
'Есть гораздо больше логики.' - Какая логика? Вы должны отделить пользовательский интерфейс от данных и бизнес-логики, и у вас больше не будет этих проблем. Кстати, создание элементов пользовательского интерфейса в процедурном коде не очень хорошая идея с точки зрения MVVM. Для этого и предназначен XAML. –
Я просто хотел избежать обсуждения. Фактически XAML-код UserControl преобразуется из xml-файлов через XSLT, а Codebehind генерируется с использованием CodeDOM. Все вещи должны быть скомпилированы и завернуты в сборку. Я использую assembly.CreateInstance(), чтобы получить экземпляр UserControl. Эта строка выбрасывает исключение. В моем графическом интерфейсе у меня есть ContentControl, который имеет привязку к UserControl в моем ViewModel – Joel
. В WPF нет необходимости в любом из них, вы могли бы решить свои потребности с помощью некоторых 'DataTemplate' и' XAMLReader', но если вы уже (что просто неправильно ИМО), то я не думаю, что вы можете сделать это, чтобы улучшить его. Вы можете создавать/манипулировать элементами пользовательского интерфейса в потоке пользовательского интерфейса. Поэтому остальная часть пользовательского интерфейса станет безответственной, пока это происходит. Люди, похоже, не понимают, что концепция WPF «динамического интерфейса» полностью отличается от большинства архаичных интерфейсов пользовательского интерфейса динозавров, и эти виды хаков совершенно не нужны в WPF. –