Подтвердить что ты не робот

Каков наилучший способ переключения представлений/пользовательских элементов в MVVM-light и WPF?

Я относительно новичок в WPF и MVVM, и самая сложная вещь, которую я нашел, - это просто переключить пользовательское управление или представление в приложении.

В winforms, чтобы удалить элемент управления, вы просто скажете это. Parent.Controls.Remove(this);

В WPF нет общего родительского элемента управления, вам придется придать ему тип к определенному типу (т.е. сетке), а затем удалить его.

Это также, похоже, нарушает архитектуру MVVM. Я также попробовал шаблоны данных и презентаторов контента, которые хорошо работают, за исключением того факта, что я не могу изменить datacontext из кода, поскольку datacontext всегда является viewmodellocator.

Являются ли страницы приемлемым способом сделать это в WPF сейчас? Что, если бы у меня была сетка с пользовательским usecontrol, и я хотел переключить ее на основе некоторой переменной в viewModel? Похоже, что простейшие задачи не могут быть легко выполнены в WPF.

4b9b3361

Ответ 1

Вы бы сделали это в своей родительской ViewModel.

Например, если ваша страница (назовите ее PageViewModel) имеет два вида (ViewModelA и ViewModelB), у вас будет свойство на PageViewModel, называемое CurrentView, и это определит, какой вид видимый. Если для PageViewModel.CurrentView установлен экземпляр ViewModelA, то для рисования содержимого используется ViewA DataTemplate. Когда он установлен в экземпляр ViewModelB, отображается ViewB DataTemplate.

<DataTemplate DataType="{x:Type local:PageViewModel}">
    <ContentControl Content="{Binding CurrentView}" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:ViewModelA}">
    <TextBlock Text="I'm ViewModelA" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:ViewModelB}">
    <TextBlock Text="I'm ViewModelB" />
</DataTemplate>

Было бы идеально назвать команду представлений switch из родительского представления (в этом случае DataTemplate для PageViewModel), однако, если вы хотите переключать представления из ViewModelA/B, вы можете либо подключить событие вручную, когда объекты создаются (CurrentView.ChangeViewCommand = this.ChangeViewCommand) или заглядывают в систему обмена сообщениями. MVVM Light имеет простой класс Messenger, который я нашел, был довольно прост в использовании, или Prism имеет более продвинутый EventAggregator

Если вы хотите переключать Views для одного и того же ViewModel, я бы рекомендовал свойство Mode, которое используется для определения того, какой вид использовать. Например:

<DataTemplate x:Key="ViewA" DataType="{x:Type local:MyViewModel}">
    <TextBlock Text="I'm ViewModelA" />
</DataTemplate>

<DataTemplate x:Key="ViewB" DataType="{x:Type local:MyViewModel}">
    <TextBlock Text="I'm ViewModelB" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:MyViewModel}">
    <ContentControl Content="{Binding }">
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Setter Property="ContentTemplate" Value="{StaticResource ViewA}" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Mode}" Value="2">
                        <Setter Property="ContentTemplate" Value="{StaticResource ViewB}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</DataTemplate>

ИЗМЕНИТЬ

Я действительно вижу, что этот вопрос возникает много, поэтому разместил что-то об этом здесь, если кому-то интересно