Итак, я настроил свое приложение таким образом.
Мой App.xaml
содержит DataTemplates для моих представлений, которые являются UserControl
s
<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType = "{x:Type vms:ProtectionViewModel}">
<view:ProtectionView />
</DataTemplate>
<DataTemplate DataType = "{x:Type vms:CloudViewModel}">
<view:CloudView />
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
А еще у меня есть MainWindow.xaml
, который состоит из 2 кнопок и ContentPresenter
<RadioButton Content = "Y"
FontSize = "16"
Foreground = "LightGray"
Padding = "0,0,0,1"
Command = "{Binding ShowProtectionViewCommand}"/>
<RadioButton Content = "Z"
FontSize = "16"
Foreground = "LightGray"
Padding = "0,0,0,1"
Command = "{Binding ShowCloudViewCommand}"/>
<ContentPresenter Content = "{Binding CurrentView}" />
И на данный момент, когда я нажимаю одну из кнопок, она меняет CurrentView
на ViewModel, которая затем меняет представление на основе ViewModel, как показано ранее в App.xaml
Делая это
private object _currentView;
public object CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged();
}
}
public ProtectionViewModel ProtectionViewModel { get; set; } = new ProtectionViewModel();
public CloudViewModel CloudViewModel { get; set; } = new CloudViewModel();
ShowProtectionViewCommand = new RelayCommand(o => { CurrentView = ProtectionViewModel; });
ShowCloudViewCommand = new RelayCommand(o => { CurrentView = CloudViewModel; });
Все работает отлично, я могу переключать вид, и он сохраняет тот же DataContext, и это здорово. Проблема в том, что если мне нужно глобальное свойство, к которому я могу получить доступ из нескольких ViewModels, что мне делать?
Глядя на это изображение, которое я нашел сюда
Я хотел создать что-то в этом стиле, но я не знаю, как бы я реализовал «Общую виртуальную машину».
У всех моих представлений есть собственная ViewModel, у MainWindow
есть MainViewModel
, у ProtectionView
есть ProtectionViewModel
и т. д.
Предполагая последнее, почему бы не сделать так, чтобы каждая модель представления выставляла свойство типа CommonVm
(это ваш единственный глобальный экземпляр CommonVm
), а затем привязывала к нему xaml?
Совместное использование одного экземпляра будет таким же, как и получение от него, не так ли? Я думал, что должен быть один экземпляр CommonVm, к которому все виртуальные машины должны иметь доступ, если им это нужно.
Нет, это было бы не то же самое. Получение от него будет означать, что у вас фактически будет 3 экземпляра CommonVm
. Совместное использование будет означать, что существует только один экземпляр
Assuming the latter, why not make each view-model expose a property of type CommonVm (that is your single, global instance of CommonVm)
Не совсем понимаю, что вы имеете в виду.
1. Создайте один глобальный экземпляр CommonVM
при запуске приложения. Создайте каждый из 3 типов Vm (VM1
, VM2
, VM3
, также известный как ProtectionViewModel
, CloudViewModel
и т. д.) и передайте этот единственный экземпляр CommonVM каждому из них в своих конструкторах. Дайте каждой из этих моделей представления общедоступное свойство, которое возвращает это CommonVM
. Привяжите свой XAML к этому свойству.
Но это внедрение зависимостей, не так ли?
Это один из способов предоставить им доступ к этой глобальной модели. Не знаю, в чем проблема, но есть и другие. Вы можете дать CommonVm
общедоступное статическое свойство экземпляра своего собственного типа, о котором они могут просто «знать», а затем таким образом выставить свойство.
Создание одноэлементного экземпляра CommonVm потребует от меня создания нового экземпляра свойства CommonVm, которое я создаю в каждом Vm, нет?
Каждая виртуальная машина может использовать свойство воплощать в жизнь, но от вас зависит, возвращает ли реализация каждой виртуальной машины другой объект или один и тот же экземпляр singleton. Я не хочу быть пренебрежительным, я думаю, вам нужно немного почитать о С#. Я объясняю здесь некоторые довольно фундаментальные аспекты, которые вы, кажется, не понимаете.
Нет, я имею в виду, что, скажем, я создаю CommonVm и реализую одноэлементный шаблон, а затем создаю общедоступное свойство типа CommonVm в любой из моих других виртуальных машин, я не могу получить доступ к каким-либо свойствам из общедоступного свойства, потому что это будет нулевым, что означает, что мне придется создать его новый экземпляр, что сделает синглтон бессмысленным.
Нет, они не будут нулевыми. Потому что их реализации свойства просто захватят статический экземпляр.
Но вы не можете привязываться к чему-то статичному.
Это не так. Я не говорю о статическом классе, я говорю об экземпляре singleton, который выставляется CommonVm из его статического свойства, НО выставляется каждым экземпляром ProtectionViewModel
и CloudViewModel
из нестатических свойств. Их нестатические свойства реализованы так, чтобы возвращать один и тот же синглтон, обращаясь к статическому CommonVm
. Пока статическое свойство в CommonVm возвращает объект, созданный с помощью оператора new(), все будет работать хорошо.
Я не думал, что ответ понадобится, но у нас заканчивается место для комментариев под вопросом, поэтому позвольте мне проиллюстрировать.
Делай вот так Вот так (придется сделать вид, что я реализовал INotifyPropertyChanged
)
public class CommonVm : INotifyPropertyChanged
{
// Static instance property
public static CommonVm Instance { get; } = new CommonVm();
// Non static properties against which you can bind.
// Imagine I wrote full implementations with INPC
public int PropertyA { get; set; }
public string PropertyB { get; set; }
}
Затем
public class CloudViewModel
{
public CommonVm CommonObject => CommonVm.Instance;
}
Затем в XAML предположим, что ваш DataContext является экземпляром CloudViewModel
<TextBox Text = "{Binding CommonObject.PropertyB}"/>
Что бы вы ни хотели сказать по этому поводу, это точно не Injection Dependency Injection.
Да, я должен был ответить на последний вопрос, мне удалось понять, к чему вы клоните, но я ценю ответ.
Являются ли ваши 3 модели просмотра полученный из
CommonVm
или вы хотите, чтобы каждая из них делилась одним экземпляром?