残念ながら、私はあなたの特定の問題を再現することができませんでした。MainWindowViewLoadedイベントハンドラーで別のスレッドを起動しました。特定のメッセージを継続的に送信するだけのスレッド。次に、SecondWindowViewでShowDialog()を呼び出しました。このビューモデルは、この特定のメッセージをリッスンするように登録されています。2番目のウィンドウのビューモデルのメッセージハンドラーが繰り返し実行されました。実際、私のビューモデルはアプリケーションの起動時にViewModelLocatorによってすでに作成されているため、ShowDailog()が呼び出される前でもハンドラーが呼び出されていました。あなたのケースで何が起こっているのかをよりよく理解するために、もう少しコードを見る必要があります(つまり、詳細ウィンドウを作成しているサービス、または問題を再現するためにコンパイルできるもの)。
代わりに、子ウィンドウに対して次のアプローチを試すことができます。アプリケーションのどこかに次のクラスを定義します。
public class ShowChildWindowMessage : MessageBase { }
public class HideChildWindowMessage : MessageBase { }
public class DisplayDetailsMessage : MessageBase { }
次に、次のChildWindowVMクラスを作成し、MainWindowVMが初期化されるのと同じ方法でViewModelLocatorで初期化します。
public class ChildWindowVM : ViewModelBase
{
private ViewModelBase m_currentContent;
public ViewModelBase CurrentContent
{
get { return m_currentContent; }
set
{
NotifySetProperty(ref m_currentContent, value, () => CurrentContent);
if (m_currentContent != null)
{
m_currentContent.Refresh();
Messenger.Default.Send(new ShowChildWindowMessage());
}
}
}
public ChildWindowVM()
{
Messenger.Default.Register<DisplayDetailsMessage>(this, OnDisplayDetails);
}
private void OnDisplayDetails(DisplayDetailsMessage msg)
{
CurrentContent = ViewModelLocator.DetailsViewModel; // or whatever view model you want to display
}
}
Refresh()メソッドはDetailsViewModelクラスで定義され、ウィンドウを表示する前に実行する初期化を処理します。CurrentContentプロパティが設定されると、メッセージがMainWindowViewに送信され、コンテンツを表示するChildWindowViewインスタンスが作成されることに注意してください。
MainWindowViewコードは次のようになります。
public partial class MainWindowView : Window
{
private ChildWindowView m_childWindowView;
public MainWindowView()
{
InitializeComponent();
Closing += () => ViewModelLocator.CleanUp();
Messenger.Default.Register<ShowChildWindowMessage>(this, OnShowChildWindow);
Messenger.Default.Register<HideChildWindowMessage>(this, OnHideChildWindow);
}
private void OnShowChildWindow(ShowChildWindowMessage msg)
{
m_childWindowView = new ChildWindowView();
m_childWindowView.ShowDialog();
}
private void OnHideChildWindow(HideChildWindowMessage msg)
{
m_childWindowView.Close();
}
}
最後のステップは、CurrentContentプロパティをChildWindowVMクラスからChildWindowViewクラスにバインドすることです。これは、ChildWindowViewのxamlで行われます。
<Window x:Class="Garmin.Cartography.AdminBucketTools.ChildWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Path=ChildWindowVm, Source={StaticResource Locator}}">
<Grid>
<ContentPresenter Content="{Binding Path=CurrentContent}" />
</Grid>
これで、電話をかけるだけで、アプリケーションのどこからでも詳細を表示できます。
Messenger.Default.Send(new DisplayDetailsMessage());
そして、あなたは呼び出すことによってプログラムでウィンドウを閉じることができます
Messenger.Default.Send(new HideChildWindowMessage());
また、MessageBaseから必要な数のクラスを派生させ、ChildWindowVMクラスに登録することもできます。次に、各メッセージハンドラーで、CurrentContentプロパティを適切なビューモデルに設定するだけで、表示するコンテンツを指定できます。
もう1つ、実際に。子ウィンドウで役立つものを実際に表示したい場合は、ビューとビューモデル間のテンプレートバインディングを指定する必要があります。これは、アプリケーションリソースのxamlを介して実行できます。
<DataTemplate DataType="{x:Type viewmodels:DetailsViewModel}">
<views:DetailsView />
</DataTemplate>
名前空間(つまり、「viewmodels」と「views」)を定義することを忘れないでください。