В моем проекте я передаю ViewModels и дочерним окнам. Я создаю свойство зависимости для ViewModel в коде моего дочернего окна, и в установщике этого свойства я передаю ViewModel вместе с ViewModel моего дочернего окна. Это означает, что вы создаете отдельный класс ViewModel только для своего дочернего окна.
Чтобы ответить на ваш второй вопрос, вы могли бы, чтобы ViewModel вашего дочернего окна содержал свойства, о которых заботится каждая вкладка, но их контекст данных по-прежнему совпадает с контекстом данных дочернего окна, поэтому у них есть доступ к общим свойствам. На самом деле это очень просто, поскольку они автоматически получают контекст данных дочернего окна.
Вот пример, иллюстрирующий две концепции выше.
Дочернее представление окна DetailsWindow.xaml (обратите внимание, что у меня есть привычка называть мои дочерние представления окна * Window.xaml вместо * View.xaml)
<controls:ChildWindow x:Class="DetailsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:Views="clr-namespace:Views"
Title="Details"
DataContext="{Binding DetailsWindowViewModel, Source={StaticResource Locator}}"
>
<Grid>
<sdk:TabControl>
<sdk:TabItem Header="First Tab" Content="{Binding FirstTabContent}" />
<sdk:TabItem Header="Second Tab" Content="{Binding SecondTabContent}" />
</sdk:TabControl>
</Grid>
</controls:ChildWindow>
Код представления дочернего окна DetailsWindow.xaml.cs и его интерфейс IDetailsWindow.cs
public partial class DetailsWindow : ChildWindow, IDetailsWindow
{
private IDetailsWindowViewModel ViewModel
{
get { return this.DataContext as IDetailsWindowViewModel; }
}
public DetailsWindow()
{
InitializeComponent();
}
#region Customer dependency property
public const string CustomerViewModelPropertyName = "Customer";
public ICustomerViewModel Customer
{
get
{
return (ICustomerViewModel)GetValue(CustomerViewModelProperty);
}
set
{
SetValue(CustomerViewModelProperty, value);
if (ViewModel != null)
{
ViewModel.Customer = value;
}
}
}
public static readonly DependencyProperty CustomerViewModelProperty = DependencyProperty.Register(
CustomerViewModelPropertyName,
typeof(ICustomerViewModel),
typeof(CustomerDetailsWindow),
null);
#endregion
}
public interface IDetailsWindow
{
ICustomerViewModel Customer { get; set; }
void Show();
}
Модель представления дочернего окна DetailsWindowViewModel.cs и ее интерфейс IDetailsWindowViewModel
public class DetailsWindowViewModel : ViewModelBase, IDetailsWindowViewModel
{
public DetailsWindowViewModel(IMessenger messenger)
: base(messenger)
{
}
#region Properties
#region Customer Property
public const string CustomerPropertyName = "Customer";
private ICustomerViewModel _customer;
public ICustomerViewModel Customer
{
get { return _customer; }
set
{
if (_customer == value)
return;
var oldValue = _customer;
_customer = value;
RaisePropertyChanged(CustomerPropertyName, oldValue, value, true);
}
}
#endregion
#region FirstTabContent Property
public const string FirstTabContentPropertyName = "FirstTabContent";
private FrameworkElement _firstTabContent;
public FrameworkElement FirstTabContent
{
get { return _firstTabContent; }
set
{
if (_firstTabContent == value)
return;
_firstTabContent = value;
RaisePropertyChanged(FirstTabContentPropertyName);
}
}
#endregion
#region SecondTabContent Property
public const string SecondTabContentPropertyName = "SecondTabContent";
private FrameworkElement _secondTabContent;
public FrameworkElement SecondTabContent
{
get { return _secondTabContent; }
set
{
if (_secondTabContent == value)
return;
_secondTabContent = value;
RaisePropertyChanged(SecondTabContentPropertyName);
}
}
#endregion
#endregion
}
public interface IDetailsWindowViewModel
{
ICustomerViewModel Customer { get; set; }
FrameworkElement FirstTabContent { get; set; }
FrameworkElement SecondTabContent { get; set; }
void Cleanup();
}
И вы можете показать дочернее окно из вашего MainPageViewModel.cs следующим образом.
public class MainViewModel : ViewModelBase, IMainViewModel
{
private readonly IDetailsWindow _detailsWindow;
public MainViewModel(IMessenger messenger, IDetailsWindow DetailsWindow)
: base(messenger)
{
_detailsWindow = DetailsWindow;
}
private void DisplayCustomerDetails(ICustomerViewModel customerToDisplay)
{
_detailsWindow.Customer = customerToDisplay;
_detailsWindow.Show();
}
}
Обратите внимание, что я создаю интерфейсы для всех моих моделей представления и дочерних окон, и я использую контейнер DI / IoC в моем ViewModelLocator, чтобы все зависимости моих ViewModels вводились для меня. Тебе не обязательно это делать, но мне нравится, как это работает.