在 mvvm 中处理多个视图的问题
probleme dealing with several view in mvvm
我目前正在构建一个具有多个视图的软件,我想通过单击当前视图上的按钮从一个视图切换到另一个视图:
当然我有超过 3 个观点,但这是为了说明这个概念。这是我从第 1 页转到第 2 页的代码。但是我无法从第 2 页转到第 3 页,我不知道出了什么问题。谢谢你的帮助。
MainWindow.xaml
<Controls:MetroWindow x:Class="maquette.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:maquette"
xmlns:viewModel ="clr-namespace:maquette.ViewModel"
xmlns:view ="clr-namespace:maquette.View"
BorderBrush="{DynamicResource AccentColorBrush}"
BorderThickness="2"
mc:Ignorable="d"
Title="MainWindow">
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:page1ViewModel}">
<local:Page1/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:page2ViewModel}">
<view:Page2/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:page3ViewModel}">
<view:Page3/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:page4ViewModel}">
<view:Page4/>
</DataTemplate>
</Window.Resources>
<Grid>
<Controls:TransitioningContentControl x:Name="pagesControl"
Content="{Binding SelectedViewModel}"
Transition="Left"
/>
</Grid>
</Controls:MetroWindow>
MainWindow.cs
public MainWindow()
{
InitializeComponent();
var viewModel = new NavigationViewModel();
viewModel.SelectedViewModel = new page1ViewModel(viewModel);
this.DataContext = viewModel;
}
NavigationViewModel.cs
public class NavigationViewModel : INotifyPropertyChanged
{
private object selectedViewModel;
public object SelectedViewModel
{
get
{
return selectedViewModel;
}
set
{
selectedViewModel = value;
OnPropertyChanged("SelectedViewModel");
}
}
/// <summary>
///
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
Page1.xaml
<UserControl x:Class="maquette.Page1"
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:maquette.View"
xmlns:viewModel="clr-namespace:maquette.ViewModel"
d:DesignHeight="300" d:DesignWidth="300"
mc:Ignorable="d"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Title"
HorizontalAlignment="Center"
TextWrapping="Wrap"
VerticalAlignment="Center"
Width="320"
FontSize="30"
Grid.ColumnSpan="2"
FontFamily="Segoe UI"
FontWeight="Bold">File Control Program</TextBlock>
<Button x:Name="button"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.RowSpan="2"
Width="180"
Height="90"
Style="{StaticResource AccentedSquareButtonStyle}"
Command="{Binding Path=goSettings}"
>
<TextBlock Text="go page 2"
TextWrapping="Wrap"
TextAlignment="Center"/>
</Button>
</Grid>
</UserControl>
page1ViewModel
class page1ViewModel
{
public ICommand goSettings { get; set; }
private readonly NavigationViewModel _navigationViewModel;
public page1ViewModel(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
goSettings = new BaseCommand(OpenSettings);
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void OpenSettings(object obj)
{
_navigationViewModel.SelectedViewModel = new page2ViewModel();
}
}
page2.xaml
<UserControl x:Class="maquette.View.Page2"
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:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:maquette.View"
xmlns:view ="clr-namespace:maquette.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Background="White">
<Grid>
<Button x:Name="button"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.ColumnSpan="2"
Grid.Row="4"
Width="180"
Height="80"
Style="{StaticResource AccentedSquareButtonStyle}"
Command="{Binding Path=goPage3}">
<TextBlock Text="Go page 3"
TextWrapping="Wrap"
TextAlignment="Center"
FontSize="20"
/>
</Button>
</Grid>
</UserControl>
page2.cs
public Page2()
{
InitializeComponent();
var viewModel = new NavigationViewModel();
DataContext = new page2ViewModel(viewModel);
}
page2ViewModel.cs
public class page2ViewModel
{
public ICommand goPage3 { get; set; }
private readonly NavigationViewModel _navigationViewModel;
public page2ViewModel()
{
}
public page2ViewModel(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
goPage3 = new BaseCommand(OpenPage3);
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void OpenPage3(object obj)
{
_navigationViewModel.SelectedViewModel = new page3ViewModel();
}
}
但是正如我所说,第 2 页和第 3 页之间的转换不起作用。有帮助吗?谢谢你 !
这是为了不使用任何mvvm框架
在主 window 视图模型中为子视图模型定义数据模板。
对于整个应用程序,您必须为主视图模型创建静态对象。
那么只会更改视图。
应该是这样的...
public partial class App : Application
{
public static MainWindowViewModel mainWindowViewModel;
public App()
{
mainWindowViewModel = new MainWindowViewModel();
}
}
在主窗口视图模型中
public class MainWindowViewmodel
{
private object selectedViewModel;
public object SelectedViewModel
{
get
{
return selectedViewModel;
}
set
{
selectedViewModel = value;
OnPropertyChanged("SelectedViewModel");
}
}
public MainWindowViewmodel()
{
SelectedViewModel = new page1viewmodel();
}
}
在
中的 Page1Viewmodel 中
class page1ViewModel
{
public ICommand goSettings { get; set; }
private readonly NavigationViewModel _navigationViewModel;
public page1ViewModel(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
goSettings = new BaseCommand(OpenSettings);
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void OpenSettings(object obj)
{
mainWindowViewModel.SelectedViewModel = new page2ViewModel();
}
}
像这样你必须实现。
这对你有帮助。
从 page2ViewModel
中删除此构造函数重载:
public page2ViewModel()
{
}
并且总是用 page1ViewModel 中唯一的 NavigationViewModel
注入它:
private void OpenSettings(object obj)
{
_navigationViewModel.SelectedViewModel = new page2ViewModel(_navigationViewModel);
}
也不要显式设置 Page2
的 DataContext
:
public Page2()
{
InitializeComponent();
}
数据模板将确保它获得正确的 DataContext
。
我目前正在构建一个具有多个视图的软件,我想通过单击当前视图上的按钮从一个视图切换到另一个视图:
当然我有超过 3 个观点,但这是为了说明这个概念。这是我从第 1 页转到第 2 页的代码。但是我无法从第 2 页转到第 3 页,我不知道出了什么问题。谢谢你的帮助。
MainWindow.xaml
<Controls:MetroWindow x:Class="maquette.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:maquette"
xmlns:viewModel ="clr-namespace:maquette.ViewModel"
xmlns:view ="clr-namespace:maquette.View"
BorderBrush="{DynamicResource AccentColorBrush}"
BorderThickness="2"
mc:Ignorable="d"
Title="MainWindow">
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:page1ViewModel}">
<local:Page1/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:page2ViewModel}">
<view:Page2/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:page3ViewModel}">
<view:Page3/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:page4ViewModel}">
<view:Page4/>
</DataTemplate>
</Window.Resources>
<Grid>
<Controls:TransitioningContentControl x:Name="pagesControl"
Content="{Binding SelectedViewModel}"
Transition="Left"
/>
</Grid>
</Controls:MetroWindow>
MainWindow.cs
public MainWindow()
{
InitializeComponent();
var viewModel = new NavigationViewModel();
viewModel.SelectedViewModel = new page1ViewModel(viewModel);
this.DataContext = viewModel;
}
NavigationViewModel.cs
public class NavigationViewModel : INotifyPropertyChanged
{
private object selectedViewModel;
public object SelectedViewModel
{
get
{
return selectedViewModel;
}
set
{
selectedViewModel = value;
OnPropertyChanged("SelectedViewModel");
}
}
/// <summary>
///
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
Page1.xaml
<UserControl x:Class="maquette.Page1"
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:maquette.View"
xmlns:viewModel="clr-namespace:maquette.ViewModel"
d:DesignHeight="300" d:DesignWidth="300"
mc:Ignorable="d"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Title"
HorizontalAlignment="Center"
TextWrapping="Wrap"
VerticalAlignment="Center"
Width="320"
FontSize="30"
Grid.ColumnSpan="2"
FontFamily="Segoe UI"
FontWeight="Bold">File Control Program</TextBlock>
<Button x:Name="button"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.RowSpan="2"
Width="180"
Height="90"
Style="{StaticResource AccentedSquareButtonStyle}"
Command="{Binding Path=goSettings}"
>
<TextBlock Text="go page 2"
TextWrapping="Wrap"
TextAlignment="Center"/>
</Button>
</Grid>
</UserControl>
page1ViewModel
class page1ViewModel
{
public ICommand goSettings { get; set; }
private readonly NavigationViewModel _navigationViewModel;
public page1ViewModel(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
goSettings = new BaseCommand(OpenSettings);
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void OpenSettings(object obj)
{
_navigationViewModel.SelectedViewModel = new page2ViewModel();
}
}
page2.xaml
<UserControl x:Class="maquette.View.Page2"
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:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:maquette.View"
xmlns:view ="clr-namespace:maquette.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Background="White">
<Grid>
<Button x:Name="button"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.ColumnSpan="2"
Grid.Row="4"
Width="180"
Height="80"
Style="{StaticResource AccentedSquareButtonStyle}"
Command="{Binding Path=goPage3}">
<TextBlock Text="Go page 3"
TextWrapping="Wrap"
TextAlignment="Center"
FontSize="20"
/>
</Button>
</Grid>
</UserControl>
page2.cs
public Page2()
{
InitializeComponent();
var viewModel = new NavigationViewModel();
DataContext = new page2ViewModel(viewModel);
}
page2ViewModel.cs
public class page2ViewModel
{
public ICommand goPage3 { get; set; }
private readonly NavigationViewModel _navigationViewModel;
public page2ViewModel()
{
}
public page2ViewModel(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
goPage3 = new BaseCommand(OpenPage3);
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void OpenPage3(object obj)
{
_navigationViewModel.SelectedViewModel = new page3ViewModel();
}
}
但是正如我所说,第 2 页和第 3 页之间的转换不起作用。有帮助吗?谢谢你 !
这是为了不使用任何mvvm框架
在主 window 视图模型中为子视图模型定义数据模板。
对于整个应用程序,您必须为主视图模型创建静态对象。
那么只会更改视图。
应该是这样的...
public partial class App : Application
{
public static MainWindowViewModel mainWindowViewModel;
public App()
{
mainWindowViewModel = new MainWindowViewModel();
}
}
在主窗口视图模型中
public class MainWindowViewmodel
{
private object selectedViewModel;
public object SelectedViewModel
{
get
{
return selectedViewModel;
}
set
{
selectedViewModel = value;
OnPropertyChanged("SelectedViewModel");
}
}
public MainWindowViewmodel()
{
SelectedViewModel = new page1viewmodel();
}
}
在
中的 Page1Viewmodel 中class page1ViewModel
{
public ICommand goSettings { get; set; }
private readonly NavigationViewModel _navigationViewModel;
public page1ViewModel(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
goSettings = new BaseCommand(OpenSettings);
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
private void OpenSettings(object obj)
{
mainWindowViewModel.SelectedViewModel = new page2ViewModel();
}
}
像这样你必须实现。
这对你有帮助。
从 page2ViewModel
中删除此构造函数重载:
public page2ViewModel()
{
}
并且总是用 page1ViewModel 中唯一的 NavigationViewModel
注入它:
private void OpenSettings(object obj)
{
_navigationViewModel.SelectedViewModel = new page2ViewModel(_navigationViewModel);
}
也不要显式设置 Page2
的 DataContext
:
public Page2()
{
InitializeComponent();
}
数据模板将确保它获得正确的 DataContext
。