Я знаю, что этот вопрос был довольно часто, но я хочу понять это, а не просто копировать код. У меня есть два UserControls и MainWindow. Я хочу добиться простой навигации: нажмите кнопку 1 -> откройте UserControl1 в Content Control. то же самое для кнопки 2 с UserControl2.
Вот что у меня получилось (немного, но все закодировано мной, так что извините, если что-то не так):
MainWindow.xaml:
<Window x:Class = "gf_mvvmlight.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:command = "http://www.galasoft.ch/mvvmlight"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:gf_mvvmlight"
mc:Ignorable = "d"
Title = "MainWindow" Height = "450" Width = "800"
DataContext = "{Binding Main, Source = {StaticResource Locator}}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName = "Loaded">
<command:EventToCommand Command = "{Binding LoadedCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
<Button>switch to Page 2</Button>
<ContentControl Content = "{Binding Page1View, Source = {StaticResource Locator}}" />
</Grid>
Page1.xaml (Page2 то же самое):
<UserControl x:Class = "gf_mvvmlight.View.Page1View"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "clr-namespace:gf_mvvmlight.View"
mc:Ignorable = "d"
d:DesignHeight = "450" d:DesignWidth = "800"
DataContext = "{Binding Path=Page1ViewModel, Source = {StaticResource Locator}}">
<Grid>
<Label>orkpwefkwe99</Label>
</Grid>
ViewModelLocater.cs:
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<Page1ViewModel>();
SimpleIoc.Default.Register<Page2ViewModel>();
}
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public Page1ViewModel Page1View
{
get
{
return ServiceLocator.Current.GetInstance<Page1ViewModel>();
}
}
public Page2ViewModel Page2View
{
get
{
return ServiceLocator.Current.GetInstance<Page2ViewModel>();
}
}
Итак, мой вопрос: как я могу сделать ContentControl динамическим и открывать Page2View, когда я нажимаю кнопку? я не за исключением кода, просто несколько советов, пожалуйста :)
и программа должна иметь возможность переключать представления из каждого класса !!!
заранее спасибо:)





Лично я никогда не видел убедительных причин для использования локатора модели представления. Обычно я удаляю его, объявляю экземпляр MainViewModel в App.xaml и ссылаюсь на него в MainWindow с помощью DataContext = "{StaticResource MainViewModel}".
Независимо от того, используете ли вы ViewModelLocator или нет, вы можете просто использовать DataTemplates для заполнения представления. Итак, в MainViewModel я обычно делаю что-то вроде этого:
private BasePage _CurrentPage;
public BasePage CurrentPage
{
get { return this._CurrentPage; }
set
{
if (this._CurrentPage != value)
{
this._CurrentPage = value;
RaisePropertyChanged(() => this.CurrentPage);
}
}
}
И я подклассифицирую BasePage к своим различным типам страниц, то есть PageViewModel1, PageViewModel2 и т.д. Затем обратно в xaml мой MainWindow выглядит так:
<Window.Resources>
<DataTemplate DataType = "{x:Type vm:PageViewModel1}">
<views:PageView1 />
</DataTemplate>
<DataTemplate DataType = "{x:Type vm:PageViewModel2}">
<views:PageView2 />
</DataTemplate>
</Window.Resources>
<ContentControl Content = "{Binding CurrentPage}" />
... где PageView1 и PageView2 - ваши пользовательские элементы управления. Итак, теперь всякий раз, когда вы устанавливаете CurrentPage на одну из своих страниц, ContentControl заполняет ее соответствующим DataTemplate.
Обратите внимание: то, что я не использую ViewModelLocator, не означает, что я не верю в использование внедрения зависимостей, на самом деле как раз наоборот. Я просто не думаю, что здесь это нужно, и есть более эффективные реализации, чем ViewModelLocator (т.е. Ninject).
ОБНОВЛЕНИЕ: уточнение этого вопроса на основе вашего вопроса ниже ... мой пример выше подразумевает, что существует 3 модели представления: MainViewModel, PageViewModel1 и PageViewModel2. XAML, который я опубликовал с DataTemplates, должен быть в вашем MainWindow, для которого DataContext установлен на экземпляр MainViewModel. Допустим, конструктор MainViewModel делает что-то вроде этого:
public MainViewModel()
{
this.CurrentPage = new PageViewModel1();
}
Эта строка кода устанавливает CurrentPage, и если вы объявили ее так же, как и я (т.е. с уведомлением об изменении свойства), тогда ContentControl в MainView будет автоматически заполнен экземпляром элемента управления PageView1. Он будет делать это, потому что 1) ContentControl привязан к свойству CurrentPage и 2) я установил DataTemplate, который эффективно говорит: «всякий раз, когда содержимое чего-либо имеет тип PageViewModel1, я хочу, чтобы вы отображали его с помощью пользовательского элемента управления PageView1. . Более того ... и это важно ... что для элемента управления PageView1 будет задан DataContext, какой является CurrentPage (т. Е. Экземпляр PageViewModel1), чтобы он мог связываться с имеющимися там свойствами. Таким образом, для каждого отображаемого представления на экране есть соответствующая модель представления со всей логикой, связанной с этим представлением.
Теперь предположим, что мы реорганизуем PageViewModel1 и PageViewModel2, чтобы принять указатель на родительский MainViewModel, и допустим, что в ответ на нажатие кнопки или что-то еще он делает следующее:
this.MyParentMainViewModel.CurrentPage = new PageViewModel2()
Теперь свойство изменилось, и платформа ответит, удалив элемент управления PageView1 и заменив его элементом управления PageView2, для которого снова установлено значение DataContext CurrentPage. Таким образом, вы «изменили страницы», но сделали это полностью на уровне модели представления и полагались на привязку данных и шаблоны данных для автоматического распространения этих изменений на уровень представления.
Очевидно, что это очень и очень простой пример, который я использую, чтобы проиллюстрировать, как работает DataTemplating. В действительности дочерние модели представления никогда не будут обращаться к своим родителям напрямую или даже когда-либо узнают о них, вы обычно используете структуру внедрения зависимостей для передачи интерфейсов дочерним элементам, которые затем обрабатываются родителем ... но это тема для другого сочинение. :)
Ответ уточнен.
Привет, Марк, спасибо за ответ! до моего решения у меня был еще один, похожий на ваш, но я не мог переключать пользовательские элементы управления из пользовательского элемента управления, только из MainWindow. как бы вы переключили текущую страницу?