【发布时间】:2021-04-20 21:29:59
【问题描述】:
再次,对于任何错误,我提前道歉,英语不是我的母语。 我正在制作一个 MVVM 应用程序,并且我想在 MainWindow 中使用 ContentControl 动态更改视图,这是代码中必须理解的部分:
首先,观点: MainWindow.xaml
<Window x:Class="Vernam.MainWindow"
x:Name="MainWindowID"
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:local="clr-namespace:Vernam"
xmlns:viewModel="clr-namespace:Vernam.ViewModels"
mc:Ignorable="d"
Height="600"
Width="900"
...>
<Window.Resources>
<viewModel:MainViewModel x:Key="vm"></viewModel:MainViewModel>
</Window.Resources>
...
<Grid>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="40"></ColumnDefinition>
<ColumnDefinition Width="454"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
...
<StackPanel Grid.Column="2" Orientation="Horizontal"
DataContext="{Binding Source={StaticResource vm}}">
<RadioButton x:Name="CorrRadioButton"
Content="Correspondences"
Width="176"
Foreground="White"
FontSize="18"
Style="{StaticResource HeadButtonTheme}"
GroupName="Head"
IsChecked="True"
Command="{Binding Path=CorrCommand}"/>
<RadioButton x:Name="ProfileRadioButton"
Content="Profile"
Width="89"
Foreground="White"
FontSize="18"
Style="{StaticResource HeadButtonTheme}"
GroupName="Head"
Command="{Binding Path=ProfileCommand}"/>
</StackPanel>
...
</Grid>
<ContentControl Grid.Row="1"
Content="{Binding CurrentView}"/>
</Grid>
</Border>
</Window>
和 MainWindow.xaml.cs:
public partial class MainWindow : Window
{
bool isMinimized = false;
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
两个视图,我想在 MainWindow 中显示:
CorrespondensesView.xaml
<UserControl x:Class="Vernam.Views.CorrespondensesView"
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:Vernam.Views"
mc:Ignorable="d"
Height="540"
Width="900">
<Grid Background="#035251">
...
</Grid>
</UserControl>
CorrespondensesView.xaml.cs
public partial class CorrespondensesView : UserControl
{
public CorrespondensesView()
{
InitializeComponent();
}
}
ProfileView.xaml:
<UserControl x:Class="Vernam.Views.ProfileView"
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:Vernam.Views"
mc:Ignorable="d"
Height="540"
Width="900">
<Grid Background="#035251">
...
</Grid>
</UserControl>
ProfileView.xaml.cs:
public partial class ProfileView : UserControl
{
public ProfileView()
{
InitializeComponent();
}
}
这里是 MainWindow 视图模型
namespace Vernam.ViewModels
{
public class MainViewModel : ObservableObject
{
private RelayCommand corrCommand;
private RelayCommand profileCommand;
private object currentView;
public CorrespondensesViewModel CorrVM { get; set; }
public ProfileViewModel ProfileVM { get; set; }
public object CurrentView
{
get { return currentView; }
set
{
currentView = value;
this.OnPropertyChanged("CurrentView");
}
}
public RelayCommand CorrCommand
{
get
{
return corrCommand ??
(corrCommand = new RelayCommand(obj =>
{
CurrentView = CorrVM;
}));
}
}
public RelayCommand ProfileCommand
{
get
{
return profileCommand ??
(profileCommand = new RelayCommand(obj =>
{
CurrentView = ProfileVM;
}));
}
}
public MainViewModel()
{
CorrVM = new CorrespondensesViewModel();
ProfileVM = new ProfileViewModel();
CurrentView = CorrVM;
}
}
}
CorrespondencesViewModel 和 ProfileViewModel 为空。
最后是 App.xaml
<Application x:Class="Vernam.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Vernam"
xmlns:viewModel="clr-namespace:Vernam.ViewModels"
xmlns:view="clr-namespace:Vernam.Views"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
...
<DataTemplate DataType="{x:Type viewModel:CorrespondensesViewModel}">
<view:CorrespondensesView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:ProfileViewModel}">
<view:ProfileView/>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
您可能需要查看 ObservableObject 类:
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
}
然后我运行应用程序,我实际上可以看到我在 MainViewModel 构造函数中分配给 CurrentView 的视图:
public MainViewModel()
{
CorrVM = new CorrespondensesViewModel();
ProfileVM = new ProfileViewModel();
CurrentView = CorrVM;
}
如果我将 CorrVM 或 ProfileVM 分配给 CurrentView,我实际上会看到 CorrespondensesView 或 ProfileView,但我无法动态更改视图:
RadioButton 命令绑定正常工作,每次点击相应按钮时都会重新分配 CurrentView,但在 MainWindow 中看不到任何变化。
所以我认为问题出在绑定上,您有什么解决方法的想法吗?
更新: 这个属性的get部分只在初始化的时候调用,所以肯定是绑定的问题。
public ObservableObject CurrentView
{
get { return currentView; }
set
{
currentView = value;
this.OnPropertyChanged("CurrentView");
}
}
尝试使用不同的绑定模式和更新触发器,但无济于事。
<ContentControl Grid.Row="1"
Content="{Binding Path=CurrentView, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"/>
【问题讨论】: