C# MVVM无法在主页上显示默认用户控件
我正在使用WPF创建一个应用程序,并尝试使用MVVM模式 我有一个主窗口,其中设置了一些在整个应用程序中使用的默认控件。C# MVVM无法在主页上显示默认用户控件,c#,wpf,mvvm,C#,Wpf,Mvvm,我正在使用WPF创建一个应用程序,并尝试使用MVVM模式 我有一个主窗口,其中设置了一些在整个应用程序中使用的默认控件。 在这个主窗口中,我设置了一个ContentControl来显示不同的子视图,具体取决于按下的导航按钮 在大多数情况下,这很好。实际的导航功能正常,因此我不太关心该代码。将显示主窗口,当我按下按钮时,所需的ContentControl将显示数据库中的正确信息 我遇到的问题是试图显示默认的ContentControl。当MainWindow首次加载时,我希望显示“主”Conten
在这个主窗口中,我设置了一个ContentControl来显示不同的子视图,具体取决于按下的导航按钮 在大多数情况下,这很好。实际的导航功能正常,因此我不太关心该代码。将显示主窗口,当我按下按钮时,所需的ContentControl将显示数据库中的正确信息 我遇到的问题是试图显示默认的ContentControl。当MainWindow首次加载时,我希望显示“主”ContentControl,而不必按下按钮 以下是我现在拥有的: MainWindowVM:
public class MainWindowVM : ViewModelBase
{
public MainWindowVM()
{
NavCommand = new NavigationCommand<string>(OnNav);
}
private MasterViewVM masterViewVM = new MasterViewVM();
private Room1ViewVM room1ViewVM = new Room1ViewVM();
private Room2ViewVM room2ViewVM = new Room2ViewVM();
private ObservableObject currentViewModel;
public ObservableObject CurrentViewModel
{
get { return currentViewModel; }
set { SetProperty(ref currentViewModel, value); }
}
public NavigationCommand<string> NavCommand { get; private set; }
private void OnNav(string destination)
{
switch (destination)
{
case "master":
CurrentViewModel = masterViewVM;
break;
case "room1":
CurrentViewModel = room1ViewVM;
break;
case "room2":
CurrentViewModel = room2ViewVM;
break;
}
}
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:MasterViewVM}">
<views:MasterView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:Room1ViewVM}" >
<views:Room1View />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:Room2ViewVM}" >
<views:Room2View />
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel Name="stackPage" Orientation="Vertical" Grid.Column="1">
<StackPanel Name="stackNavButtons"
Orientation="Horizontal"
Grid.Column="1" Grid.ColumnSpan="4"
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
>
<Button Name="btnMaster"
Content="Master"
Height="50"
Width="75"
Command="{Binding NavCommand}"
CommandParameter="master"
/>
<Button Name="btnRoom1"
Content="Room 1"
Height="50"
Width="75"
Command="{Binding NavCommand}"
CommandParameter="room1"
/>
<Button Name="btnRoom2"
Content="Room 2"
Height="50"
Width="75"
Command="{Binding NavCommand}"
CommandParameter="room2"
/>
</StackPanel>
<ContentControl Content="{Binding CurrentViewModel}" />
</StackPanel>
</Grid>
为了在打开主窗口(并试图显示主窗口)之前加载数据,我尝试将以下内容添加到上述方法中
我最后一次尝试是完全按照Rachel Lim的博客中提供的指导来重建程序。
我不打算在这里包含修改过的代码,因为我最终得到了相同的结果
我能够让Rachel的示例应用程序正常工作。但是,它没有连接到数据库。这进一步表明,我的问题在于何时和/或如何将数据加载到主视图中
我现在所要做的只是在显示MainWindow时让Master显示为初始ContentControl
编辑:根据IBebs的建议更改“currentViewModel”的大小写(大写改为小写)解决了这个问题。
现在,构造函数的内容如下:
public MainWindowVM()
{
NavCommand = new NavigationCommand<string>(OnNav);
currentViewModel = masterViewVM;
}
我不确定这是否能更好地处理空值,但似乎有可能。我担心问题中没有足够的信息可以肯定地回答(例如,您是否使用Microsoft.VisualStudio.PlatformUI库?ViewModelBase在哪里定义?)但我猜ViewModelBase在调用PropertyChanged事件之前不会检查null,该事件将由
SetProperty(ref currentViewModel,value)
调用调用
为了解决这个问题,我将:
a) 确保ViewModelBase在调用PropertyChanged事件之前检查null,该事件通常按以下方式执行(取自ObservableObject代码):
b) 将初始视图模型指定给字段而不是属性,这将不会导致触发属性更改事件。因此,建造商应:
public MainWindowVM()
{
NavCommand = new NavigationCommand<string>(OnNav);
currentViewModel = masterViewVM; // Note lower case 'c' on currentViewModel
}
publicMainWindowVM()
{
NavCommand=新导航命令(OnNav);
currentViewModel=masterViewVM;//注意currentViewModel上的小写字母“c”
}
希望有帮助。恐怕问题中没有足够的信息可以肯定地回答(例如,您是否使用Microsoft.VisualStudio.PlatformUI库?ViewModelBase在哪里定义?)但我猜ViewModelBase在调用PropertyChanged事件之前不会检查null,该事件将由
SetProperty(ref currentViewModel,value)
调用调用
为了解决这个问题,我将:
a) 确保ViewModelBase在调用PropertyChanged事件之前检查null,该事件通常按以下方式执行(取自ObservableObject代码):
b) 将初始视图模型指定给字段而不是属性,这将不会导致触发属性更改事件。因此,建造商应:
public MainWindowVM()
{
NavCommand = new NavigationCommand<string>(OnNav);
currentViewModel = masterViewVM; // Note lower case 'c' on currentViewModel
}
publicMainWindowVM()
{
NavCommand=新导航命令(OnNav);
currentViewModel=masterViewVM;//注意currentViewModel上的小写字母“c”
}
希望有帮助。完美!!非常感谢你。更改currentViewModel的案例解决了这个问题。完美!!非常感谢你。更改currentViewModel的案例解决了此问题。
public class ObservableObject : INotifyPropertyChanged
{
protected virtual void SetProperty<T>(ref T member, T val, [CallerMemberName] string propertyName = null)
{
if (object.Equals(member, val)) return;
member = val;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged == null)
return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged == null)
return;
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public MainWindowVM()
{
NavCommand = new NavigationCommand<string>(OnNav);
currentViewModel = masterViewVM; // Note lower case 'c' on currentViewModel
}