在 wpf mvvm 中切换视图
Switching Views in wpf mvvm
我有 2 个视图登录并且 usermodule.I 如果登录是 success.I 想切换到用户模块已经在主窗口中制作了数据模板并且由 currentviewmodel.I 绑定的内容控件制作了一个切换视图成功后调用 MainWindowViewModel 中的方法 login.As 登录成功 currentviewmodel 更改为 usermoduleviewmodel 但视图未更改。
我是这样做的:
MainWinodow.xaml
<Window.Resources>
<DataTemplate DataType="{x:Type VM:LoginViewModel}">
<local:LoginView></local:LoginView>
</DataTemplate>
<DataTemplate DataType="{x:Type VM:MenuViewModel}">
<local:MenuWindow />
</DataTemplate>
<DataTemplate DataType="{x:Type VM:UserModuleMapViewModel}">
<local:UserModuleMapView />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentPresenter x:Name="Pages" Content="{Binding CurrentViewModel}"
Grid.Row="1"/>
</Grid>
MainWindow.cs
MainWindowViewModel mainVM = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = mainVM;
}
MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
{
readonly LoginViewModel _loginViewModel = new LoginViewModel();
readonly MenuViewModel _menuViewModel = new MenuViewModel();
readonly UserModuleMapViewModel _usermodmapViewModel = new UserModuleMapViewModel();
public MainWindowViewModel()
{
CurrentViewModel = _loginViewModel;
}
private ViewModelBase _currentViewModel;
public ViewModelBase CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if (_currentViewModel == value)
return;
_currentViewModel = value;
OnPropertyChanged("CurrentViewModel");
}
}
public void switchView()
{
if (CurrentViewModel == _loginViewModel)
{
CurrentViewModel = _usermodmapViewModel;
}
else
{
CurrentViewModel = _loginViewModel;
}
}
}
LoginViewModel.cs
public LoginModel objmodel { get; set; }
public ICommand LoginCommand { get; set; }
public LoginModel _selectedItem { get; set; }
public LoginModel SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
OnPropertyChanged("comboBoxItems");//need to check now its working properly
}
}
readonly UserModuleMapViewModel _usermodmapViewModel = new UserModuleMapViewModel();
public LoginViewModel()
{
getjobkeycodeCombobox();
objmodel = new LoginModel();
LoginCommand = new RelayCommand(() => Login());
}
public void Login()
{
try
{
UserIdInfo info = new UserIdInfo();
{
objmodel.job_Code_Key = SelectedItem.job_Code_Key;
info.EMP_NO = objmodel.EMP_NO;
info.Password = objmodel.Password;
info.Job_Code_Key = objmodel.job_Code_Key;
if (objmodel.EMP_NO == null || objmodel.EMP_NO == "" || objmodel.Password == null || objmodel.Password == "")
{
MessageBox.Show("Please Enter the inputs of all the fields..!!");
}
else
{
UserIdBL uidBL = new UserIdBL();
if (uidBL.isvalid(info))
{
MessageBox.Show("Success..!!");
MainWindowViewModel mwvm = new MainWindowViewModel();
mwvm.CurrentViewModel = _usermodmapViewModel;
//Messenger.Default.Send(new NotificationMessage("LoginSuccess"));
}
else
{
}
}
}
}
}
哪里出错了?我是不是漏了什么>
一种可能的解决方案是使用 Prism 的 IEventAggregator。您将创建一个 class 这是一个 PubSub 事件,例如
public class 登录成功事件:PubSubEvent { }
然后使用事件聚合器的实例在主视图模型中订阅该事件,例如
myEventAggregator.GetEvent().Subscribe((obj) => { SomeMethodInMainViewModel(obj); });
然后在登录成功时从登录视图模型中发布事件,例如
myEventAggregator.GetEvent().Publish(someLocalObject);
我已经在我的一个项目中成功地使用了它,但可能已经有 6 个月没有更新棱镜库了,但只要最新版本有这个功能就应该很好。取决于您是否需要在您的项目中使用第三方库。
或者..
您可以将一个 Action 传递给登录视图模型构造函数,该构造函数指向主视图模型上将当前视图模型设置为主视图模型的方法,并让登录视图模型在登录成功时调用该 Action
ContentPresenter 未更新的原因是视图绑定到 MainWindowViewModel
的不同实例。所以 MainWindow
DataContext 绑定到一个在此处创建的实例:
// MainWindow.cs
MainWindowViewModel mainVM = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = mainVM;
}
虽然 LoginViewModel
创建了一个 MainWindowViewModel
的新实例,它没有绑定到任何东西:
// LoginViewModel.cs
MainWindowViewModel mwvm = new MainWindowViewModel();
mwvm.CurrentViewModel = _usermodmapViewModel;
这就是为什么当您在 Login
方法中设置 mwvm.CurrentViewModel
属性 时绑定不会被触发。
因此,为了实现您正在尝试做的事情,您可以订阅 MainWindowViewModel
登录成功消息并在那里设置当前视图模型。这是一个使用 MVVM Light messenger 的简单示例:
// LoginViewModel.cs
if (uidBL.isvalid(info))
{
MessageBox.Show("Success..!!");
// MainWindowViewModel mwvm = new MainWindowViewModel();
// mwvm.CurrentViewModel = _usermodmapViewModel;
// send message to all subscribers
Messenger.Default.Send(new NotificationMessage("LoginSuccess"));
}
// MainWindowViewModel.cs
Messenger.Default.Register<NotificationMessage>(this, (message) =>
{
switch (message.Notification)
{
case "LoginSuccess":
CurrentViewModel = _usermodmapViewModel;
break;
default:
break;
}
});
我有 2 个视图登录并且 usermodule.I 如果登录是 success.I 想切换到用户模块已经在主窗口中制作了数据模板并且由 currentviewmodel.I 绑定的内容控件制作了一个切换视图成功后调用 MainWindowViewModel 中的方法 login.As 登录成功 currentviewmodel 更改为 usermoduleviewmodel 但视图未更改。
我是这样做的: MainWinodow.xaml
<Window.Resources>
<DataTemplate DataType="{x:Type VM:LoginViewModel}">
<local:LoginView></local:LoginView>
</DataTemplate>
<DataTemplate DataType="{x:Type VM:MenuViewModel}">
<local:MenuWindow />
</DataTemplate>
<DataTemplate DataType="{x:Type VM:UserModuleMapViewModel}">
<local:UserModuleMapView />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentPresenter x:Name="Pages" Content="{Binding CurrentViewModel}"
Grid.Row="1"/>
</Grid>
MainWindow.cs
MainWindowViewModel mainVM = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = mainVM;
}
MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
{
readonly LoginViewModel _loginViewModel = new LoginViewModel();
readonly MenuViewModel _menuViewModel = new MenuViewModel();
readonly UserModuleMapViewModel _usermodmapViewModel = new UserModuleMapViewModel();
public MainWindowViewModel()
{
CurrentViewModel = _loginViewModel;
}
private ViewModelBase _currentViewModel;
public ViewModelBase CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if (_currentViewModel == value)
return;
_currentViewModel = value;
OnPropertyChanged("CurrentViewModel");
}
}
public void switchView()
{
if (CurrentViewModel == _loginViewModel)
{
CurrentViewModel = _usermodmapViewModel;
}
else
{
CurrentViewModel = _loginViewModel;
}
}
}
LoginViewModel.cs
public LoginModel objmodel { get; set; }
public ICommand LoginCommand { get; set; }
public LoginModel _selectedItem { get; set; }
public LoginModel SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
OnPropertyChanged("comboBoxItems");//need to check now its working properly
}
}
readonly UserModuleMapViewModel _usermodmapViewModel = new UserModuleMapViewModel();
public LoginViewModel()
{
getjobkeycodeCombobox();
objmodel = new LoginModel();
LoginCommand = new RelayCommand(() => Login());
}
public void Login()
{
try
{
UserIdInfo info = new UserIdInfo();
{
objmodel.job_Code_Key = SelectedItem.job_Code_Key;
info.EMP_NO = objmodel.EMP_NO;
info.Password = objmodel.Password;
info.Job_Code_Key = objmodel.job_Code_Key;
if (objmodel.EMP_NO == null || objmodel.EMP_NO == "" || objmodel.Password == null || objmodel.Password == "")
{
MessageBox.Show("Please Enter the inputs of all the fields..!!");
}
else
{
UserIdBL uidBL = new UserIdBL();
if (uidBL.isvalid(info))
{
MessageBox.Show("Success..!!");
MainWindowViewModel mwvm = new MainWindowViewModel();
mwvm.CurrentViewModel = _usermodmapViewModel;
//Messenger.Default.Send(new NotificationMessage("LoginSuccess"));
}
else
{
}
}
}
}
}
哪里出错了?我是不是漏了什么>
一种可能的解决方案是使用 Prism 的 IEventAggregator。您将创建一个 class 这是一个 PubSub 事件,例如
public class 登录成功事件:PubSubEvent { }
然后使用事件聚合器的实例在主视图模型中订阅该事件,例如
myEventAggregator.GetEvent().Subscribe((obj) => { SomeMethodInMainViewModel(obj); });
然后在登录成功时从登录视图模型中发布事件,例如
myEventAggregator.GetEvent().Publish(someLocalObject);
我已经在我的一个项目中成功地使用了它,但可能已经有 6 个月没有更新棱镜库了,但只要最新版本有这个功能就应该很好。取决于您是否需要在您的项目中使用第三方库。
或者..
您可以将一个 Action 传递给登录视图模型构造函数,该构造函数指向主视图模型上将当前视图模型设置为主视图模型的方法,并让登录视图模型在登录成功时调用该 Action
ContentPresenter 未更新的原因是视图绑定到 MainWindowViewModel
的不同实例。所以 MainWindow
DataContext 绑定到一个在此处创建的实例:
// MainWindow.cs
MainWindowViewModel mainVM = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = mainVM;
}
虽然 LoginViewModel
创建了一个 MainWindowViewModel
的新实例,它没有绑定到任何东西:
// LoginViewModel.cs
MainWindowViewModel mwvm = new MainWindowViewModel();
mwvm.CurrentViewModel = _usermodmapViewModel;
这就是为什么当您在 Login
方法中设置 mwvm.CurrentViewModel
属性 时绑定不会被触发。
因此,为了实现您正在尝试做的事情,您可以订阅 MainWindowViewModel
登录成功消息并在那里设置当前视图模型。这是一个使用 MVVM Light messenger 的简单示例:
// LoginViewModel.cs
if (uidBL.isvalid(info))
{
MessageBox.Show("Success..!!");
// MainWindowViewModel mwvm = new MainWindowViewModel();
// mwvm.CurrentViewModel = _usermodmapViewModel;
// send message to all subscribers
Messenger.Default.Send(new NotificationMessage("LoginSuccess"));
}
// MainWindowViewModel.cs
Messenger.Default.Register<NotificationMessage>(this, (message) =>
{
switch (message.Notification)
{
case "LoginSuccess":
CurrentViewModel = _usermodmapViewModel;
break;
default:
break;
}
});