SOに関するこのトピックにはいくつかの回答があることは知っていますが、私のために働く解決策を得ることができません。データ テンプレート内から起動された ICommand から、新しいウィンドウを開こうとしています。新しいウィンドウがインスタンス化されると(「new MessageWindowP」内で) 、次の両方で前述のエラーが発生します。
TPL/FromCurrentSynchronizationContext Update の使用: 動作します
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 の使用: 更新: 推奨されません。Jon の回答を参照してください
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 Update: 非推奨 Jon's answer を参照
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();
}
}
同じスレッド で更新: 既に UI スレッドを使用している場合に機能します
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、最初/メイン ウィンドウ Update のディスパッチャへの参照を使用: 動作
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;
私は途方に暮れています。