Я знаю, что есть несколько ответов на эту тему на SO, но я не могу получить ни одно из решений, работающих на меня. Я пытаюсь открыть новое окно из ICommand, запущенного из шаблона данных. Оба следующих варианта дают вышеупомянутую ошибку при создании экземпляра нового окна(в «новом MessageWindowP»):
Использование TPL/FromCurrentSynchronizationContextОбновление :работает
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(new Action<object>(CreateMessageWindow), user,CancellationToken.None, TaskCreationOptions.None,scheduler);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
Использование ThreadStart:Обновление :не рекомендуется, см. ответ Джона
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var t = new ParameterizedThreadStart(CreateMessageWindow);
var thread = new Thread(t);
thread.SetApartmentState(ApartmentState.STA);
thread.Start(sender);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
Спасибо
РЕДАКТИРОВАТЬ. Основываясь на ответах до сих пор, я хотел бы отметить, что я также пробовал BeginInvoke в текущем диспетчере, а также выполнял код в исходном методе (, так код запускался ).См. ниже:
BeginInvokeОбновление :не рекомендуется см. ответ Джона
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
Dispatcher.CurrentDispatcher.BeginInvoke(new Action<object>(CreateMessageWindow), sender);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
В том же потокеОбновление :работает, если вы уже находитесь в потоке пользовательского интерфейса
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
}
BeginInvoke, используя ссылку на диспетчер первого /main windowОбновление :работает
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
GeneralManager.MainDispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action(() => this.CreateMessageWindow(user)));
}
}
, где GeneralManager.MainDispatcher — это ссылка на Dispatcher первого окна, которое я создаю:
[somewhere far far away]
mainP = new MainP();
MainDispatcher = mainP.View.Dispatcher;
Я в недоумении.