Закрытие одной View при открытии другой C# WPF MVVM

252
15 октября 2017, 20:44

Здравствуйте! Предположим имеется два представления. View1 появляется при загрузке формы, а View2 по нажатию на кнопку. Как можно сделать так, чтобы при появлении View2 View1 исчезло? На данный момент у меня появляется View2, но View1 остаётся висеть и просвечиваться через View2

Представления биндятся следующим образом: MainWindow.xaml

<Window.Resources>
    <DataTemplate x:Name="v1" DataType="{x:Type viewmodels:View1ViewModel}">
        <views:View1 DataContext="{Binding}"/>
    </DataTemplate>
    <DataTemplate x:Name="v2" DataType="{x:Type viewmodels:View2ViewModel}">
        <views:View2 DataContext="{Binding}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <ContentControl Content="{Binding}"/>
</Grid>

Во View1 идёт привязка

<ContentControl Content="{Binding View2}"/>

По нажатию кнопки срабатывает команда

private RelayCommand showView2;
    public RelayCommand ShowView2
    {
        get
        {
            return showView2 ??
                (showView2= new RelayCommand(obj =>
                {
                    View2Form = new View2ViewModel();
                }));
        }
    }

Свойство View2, которое будет отображаться

private object view2Form;
    public object View2Form
    {
        get { return view2Form; }
        set
        {
            if (Equals(view2Form, value))
                return;
            view2Form= value;
            OnPropertyChanged("View2Form");
        }
    }
Answer 1

Ну вы почти сделали всё правильно, смена View через ContentControl — хороший, правильный путь. Просто вы не протянули команду во View1, и поэтому включаете View2 не там, где надо: на уровне View2, а не на уровне корневой VM.

Вот наброски того, как должно быть.

Для начала, VM для первого и второго View.

class View1ViewModel
{
    public View1ViewModel(ICommand showView2) { ShowView2 = showView2; }
    public ICommand ShowView2 { get; }
}
class View2ViewModel
{
}

View1ViewModel должна выставлять команду перехода во второй View.

Теперь, главная VM. Я написал стандартную реализацию INotifyPropertyChanged (она у вас, по идее, должна быть в родительском классе). А также переименовал View2Form в SubViewModel. Команду смены VM я передаю View1ViewModel в конструкторе (сама View1ViewModel эту команду создать не может, т. к. эта команда должна менять свойства главной VM!).

class MainVM : INotifyPropertyChanged
{
    public MainVM()
    {
        ShowView2 = new RelayCommand(obj => SubViewModel = new View2ViewModel());
        SubViewModel = new View1ViewModel(ShowView2);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private object subViewModel;
    public object SubViewModel
    {
        get { return subViewModel; }
        set
        {
            if (Equals(subViewModel, value))
                return;
            subViewModel = value;
            OnPropertyChanged();
        }
    }
    protected void OnPropertyChanged([CallerMemberName]string propertyName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    public ICommand ShowView2 { get; }
}

View1 выглядит просто:

<Button Command="{Binding ShowView2}"
        HorizontalAlignment="Center" VerticalAlignment="Center"
        Content="Show View 2"/>

И View2:

<TextBlock TextAlignment="Center" VerticalAlignment="Center"
           Text="I am View 2"/>

Главное окно практически без изменений (только привязка к SubViewModel):

<Window.Resources>
    <DataTemplate DataType="{x:Type viewmodels:View1ViewModel}">
        <views:View1 DataContext="{Binding}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type viewmodels:View2ViewModel}">
        <views:View2 DataContext="{Binding}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <ContentControl Content="{Binding SubViewModel}"/>
</Grid>

Результат:

READ ALSO
.NET 4.5 C# | NewTonSoft JSON

.NET 4.5 C# | NewTonSoft JSON

В итоге получаем

261
Наследование классов, переопределение

Наследование классов, переопределение

Делаю потиху задания из решебника и это на третьем пункте меня выбило немного из колеи

210
Сериализация Item&#39;ов

Сериализация Item'ов

Подскажите, как сериализовать созданные Item'ы в панели, их текст, значение CheckBox и кнопку Delete, и дессериализовать при перезапуске программы?...

187
Получение координат в C#

Получение координат в C#

Собственно как получить координаты через gps/wifi/ip? В интернете нашёл видео, где пишут что-то типа

244