WPF MVVM - Смена UserControl в одном окне

126
20 февраля 2021, 10:10

Есть пару UserControl: AuthControl и CalculateControl. Для этих контролов есть ViewModel: AuthViewModel.cs, CalculateViewModel.cs, также имеется RootVM, в котором устанавливается нужная VM свойству CurrentContentVM. RootVM:

public RootViewModel(ViewModelBase view)
        {
            CurrentContentVM = view;
        }
        private ViewModelBase currentContentVM;
        public ViewModelBase CurrentContentVM
        {
            get
            {
                return currentContentVM;
            }
            set
            {
                currentContentVM = value;
                RaisePropertyChanged(() => CurrentContentVM);
            }
        }

Необходимо реализовать переход с контрола AuthControl в контрол CalculateControl. Я это сделал так: код MainWindow.xaml:

<Window.Resources>
        <DataTemplate DataType="{x:Type vm:AuthViewModel}">
            <local:AuthControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CalculateViewModel}">
            <view:CalculateControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CaloriesViewModel}">
            <view:CaloriesControl/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ContentControl Content="{Binding CurrentContentVM}"/>
    </Grid> 

код AuthViewModel

private string _fieldFio;
        RootViewModel root;
        public string FieldFio
        {
            get
            {
                return _fieldFio;
            }
            set
            {
                _fieldFio = value;
                RaisePropertyChanged(() => FieldFio);
            }
        }
        public ICommand CommandLogin //Это команда на кнопке
        {
            get
            {
                return _commandLogin ?? (_commandLogin = new RelayCommand(() => {
                    if (!string.IsNullOrEmpty(FieldFio) && FieldFio.Equals("Admin"))                    
                        root = new RootViewModel(new CaloriesViewModel());                    
                    else
                        MessageBox.Show("Неверный формат входной строки");
                }));
            }
        }

DataContext я устанавливаю прямо в коде:

public MainWindow()
        {
            InitializeComponent();            
            DataContext = new ViewModels.RootViewModel(new ViewModels.AuthViewModel());
        }

В общем беда в том, что при нажатии на кнопку контрол не меняется. Что можете подсказать? (Использую MVVM Light)

Answer 1

DataContext устанавливается один раз при инициализации главной формы и больше никогда не изменяется. Изменяется только CurrentContentVM в xaml. Поэтому насчет нарушения я бы с вами поспорил.

Разобрался. Вот решение, может кому пригодится: В MainWindow.xaml устанавливаем DataContext на RootViewModel:

<Window.Resources>
        <DataTemplate DataType="{x:Type vm:AuthViewModel}">
            <local:AuthControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CalculateViewModel}">
            <view:CalculateControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CaloriesViewModel}">
            <view:CaloriesControl/>
        </DataTemplate>
    </Window.Resources>
    <Window.DataContext>
        <vm:RootViewModel />
    </Window.DataContext>
    <Grid>
        <ContentControl Content="{Binding CurrentContentVM}"/>
    </Grid> 

В RootViewModel объявляем статическое поле root. В конструкторе указываем начальную форму и далее root присваиваем текущую ссылку.

public static RootViewModel root;
        public RootViewModel()
        {
            CurrentContentVM = new AuthViewModel();
            root = this;
        }   

В AuthViewModel для смены контрола просто пишем:

RootViewModel.root.CurrentContentVM = new CalculateViewModel();
Answer 2
DataContext =  ViewModels.RootViewModel(ViewModels.AuthViewModel());
READ ALSO
C# Консоль, Запретить ввод

C# Консоль, Запретить ввод

Есть консольное приложение, и обработчик нажатия кнопокНо при нажатии на какую либо клавишу, выполняется и действие, и вводится символ на экран

104
element complexType name attribute

element complexType name attribute

Как добавить или изменить имя элемента ComplexType? Мне нужно чтобы было так:

126
Не работает GetChild после Destroy в том же фрейме

Не работает GetChild после Destroy в том же фрейме

Почему данный код не работает?

80