Graeme_Grant
Нет, это неверно. Виртуальная машина не должна содержать никакого кода пользовательского интерфейса.
Есть много различных способов сделать то, что вы хотите. Мне нравится пользоваться классом обслуживания. Ниже приведен базовый (неполный) сервис, которым вы можете воспользоваться. Вам нужно будет обновить его для ваших нужд.
public interface IWindowService
{
void ShowWindow<T>(T viewModel);
}
public class WindowService : IWindowService
{
public void ShowWindow<T>(T viewModel)
{
var window = Application.Current
.Windows
.OfType<WindowDialog>()
.FirstOrDefault(x => x.Content?.GetType() == viewModel.GetType());
if (window == null)
{
window = new WindowDialog { Content = viewModel };
window.Title = "This is a title";
window.Owner = Application.Current.Windows[0];
window.Show();
}
else
{
window.Activate();
}
}
}
Вот
WindowDialog
Окно для размещения "оконных видов":
<Window
x:Class="MvvmShowWindow.WindowDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
WindowStyle="SingleBorderWindow" WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">
</Window>
Далее нам понадобится пара тестовых "оконных видов":
<UserControl
x:Class="MvvmShowWindow.Window1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="600">
<Grid>
<Viewbox>
<TextBlock Text="WINDOW 1"/>
</Viewbox>
</Grid>
</UserControl>
<UserControl
x:Class="MvvmShowWindow.Window2View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="600">
<Grid>
<Viewbox>
<TextBlock Text="WINDOW 2"/>
</Viewbox>
</Grid>
</UserControl>
И соответствующие модели просмотра для "оконных видов":
class Window1ViewModel : ViewModelBase
{
// The "Window View" VM code goes here...
}
class Window2ViewModel : ViewModelBase
{
// The "Window View" VM code goes here...
}
Далее нам нужно связать виртуальные машины с представлениями. Вот я и делаю это в приложении.Xaml:
<Application.Resources>
<DataTemplate DataType="{x:Type local:Window1ViewModel}">
<local:Window1View/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Window2ViewModel}">
<local:Window2View/>
</DataTemplate>
</Application.Resources>
Теперь мы готовы использовать сервис в MainViewModel:
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
ShowCommand = new RelayCommand<string>(CommandShow);
}
public ICommand ShowCommand { get; }
private IWindowService Service = new WindowService();
private void CommandShow(string msg)
{
switch (msg)
{
case "w1":
Service.ShowWindow(new Window1ViewModel());
break;
case "w2":
Service.ShowWindow(new Window2ViewModel());
break;
}
}
}
И главное окно для запуска теста:
<Window
x:Class="MvvmShowWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MvvmShowWindow"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
Title="MVVM Windows" Height="350" Width="525" >
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Button Content="Window1" Margin="10 5" Padding="10,5"
Command="{Binding ShowCommand}" CommandParameter="w1"/>
<Button Content="Window2" Margin="10 5" Padding="10,5"
Command="{Binding ShowCommand}" CommandParameter="w2"/>
</StackPanel>
</Grid>
</Window>