Как получить доступ к одному и тому же свойству из двух отдельных ViewModels без внедрения зависимостей?

Итак, я настроил свое приложение таким образом.

Мой App.xaml содержит DataTemplates для моих представлений, которые являются UserControls

<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, что мне делать?

Глядя на это изображение, которое я нашел сюда
Я хотел создать что-то в этом стиле, но я не знаю, как бы я реализовал «Общую виртуальную машину». Как получить доступ к одному и тому же свойству из двух отдельных ViewModels без внедрения зависимостей?

У всех моих представлений есть собственная ViewModel, у MainWindow есть MainViewModel, у ProtectionView есть ProtectionViewModel и т. д.

Являются ли ваши 3 модели просмотра полученный из CommonVm или вы хотите, чтобы каждая из них делилась одним экземпляром?

Joe 06.04.2022 22:30

Предполагая последнее, почему бы не сделать так, чтобы каждая модель представления выставляла свойство типа CommonVm (это ваш единственный глобальный экземпляр CommonVm), а затем привязывала к нему xaml?

Joe 06.04.2022 22:35

Совместное использование одного экземпляра будет таким же, как и получение от него, не так ли? Я думал, что должен быть один экземпляр CommonVm, к которому все виртуальные машины должны иметь доступ, если им это нужно.

JohnA 06.04.2022 22:35

Нет, это было бы не то же самое. Получение от него будет означать, что у вас фактически будет 3 экземпляра CommonVm. Совместное использование будет означать, что существует только один экземпляр

Joe 06.04.2022 22:36
Assuming the latter, why not make each view-model expose a property of type CommonVm (that is your single, global instance of CommonVm) Не совсем понимаю, что вы имеете в виду.
JohnA 06.04.2022 22:37

1. Создайте один глобальный экземпляр CommonVM при запуске приложения. Создайте каждый из 3 типов Vm (VM1, VM2, VM3, также известный как ProtectionViewModel, CloudViewModel и т. д.) и передайте этот единственный экземпляр CommonVM каждому из них в своих конструкторах. Дайте каждой из этих моделей представления общедоступное свойство, которое возвращает это CommonVM. Привяжите свой XAML к этому свойству.

Joe 06.04.2022 22:45

Но это внедрение зависимостей, не так ли?

JohnA 06.04.2022 22:47

Это один из способов предоставить им доступ к этой глобальной модели. Не знаю, в чем проблема, но есть и другие. Вы можете дать CommonVm общедоступное статическое свойство экземпляра своего собственного типа, о котором они могут просто «знать», а затем таким образом выставить свойство.

Joe 06.04.2022 22:49

Создание одноэлементного экземпляра CommonVm потребует от меня создания нового экземпляра свойства CommonVm, которое я создаю в каждом Vm, нет?

JohnA 06.04.2022 22:54

Каждая виртуальная машина может использовать свойство воплощать в жизнь, но от вас зависит, возвращает ли реализация каждой виртуальной машины другой объект или один и тот же экземпляр singleton. Я не хочу быть пренебрежительным, я думаю, вам нужно немного почитать о С#. Я объясняю здесь некоторые довольно фундаментальные аспекты, которые вы, кажется, не понимаете.

Joe 06.04.2022 22:59

Нет, я имею в виду, что, скажем, я создаю CommonVm и реализую одноэлементный шаблон, а затем создаю общедоступное свойство типа CommonVm в любой из моих других виртуальных машин, я не могу получить доступ к каким-либо свойствам из общедоступного свойства, потому что это будет нулевым, что означает, что мне придется создать его новый экземпляр, что сделает синглтон бессмысленным.

JohnA 06.04.2022 23:10

Нет, они не будут нулевыми. Потому что их реализации свойства просто захватят статический экземпляр.

Joe 07.04.2022 00:04

Но вы не можете привязываться к чему-то статичному.

JohnA 07.04.2022 00:06

Это не так. Я не говорю о статическом классе, я говорю об экземпляре singleton, который выставляется CommonVm из его статического свойства, НО выставляется каждым экземпляром ProtectionViewModel и CloudViewModel из нестатических свойств. Их нестатические свойства реализованы так, чтобы возвращать один и тот же синглтон, обращаясь к статическому CommonVm. Пока статическое свойство в CommonVm возвращает объект, созданный с помощью оператора new(), все будет работать хорошо.

Joe 07.04.2022 01:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
14
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не думал, что ответ понадобится, но у нас заканчивается место для комментариев под вопросом, поэтому позвольте мне проиллюстрировать.

Делай вот так Вот так (придется сделать вид, что я реализовал 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.

Да, я должен был ответить на последний вопрос, мне удалось понять, к чему вы клоните, но я ценю ответ.

JohnA 07.04.2022 02:49

Другие вопросы по теме