在wpf mvvm中切换视图

时间:2018-02-07 04:46:28

标签: mvvm views datatemplate contentcontrol

我有2个视图登录和usermodule.I想要在登录成功时切换到usermodule。我在mainwindow中创建了数据窗口,并且通过currentviewmodel进行了绑定的内容控件。我在MainWindowViewModel中创建了一个switchview方法,该方法在成功后调用登录。登录成功后,currentviewmodel变为usermoduleviewmodel bur,视图不会改变。

我这样做了: 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
                    {
                    }
                }
            }
        }


    }

我犯了什么错误?我错过了什么&gt;

2 个答案:

答案 0 :(得分:0)

一种可能的解决方案是使用Prism的IEventAggregator。您创建了一个PubSub事件的类,例如。

公共类LoginSuccessfulEvent:PubSubEvent {}

然后使用事件聚合器的实例在主视图模型中订阅该事件,例如。

myEventAggregator.GetEvent()。订阅((obj)=&gt; {SomeMethodInMainViewModel(obj);});

然后在登录成功时从登录视图模型中发布事件,例如

myEventAggregator.GetEvent()出版(someLocalObject);

我已经在我的一个项目中成功使用了这个,但可能没有更新prism lib 6个月,但只要最新版本具有此功能,它应该是好的。取决于您是否需要项目中的第三方库。

或..

您可以将一个Action传递给登录视图模型构造函数,该构造函数指向主视图模型上的一个方法,该方法将当前视图模型设置为主视图模型,并使登录视图模型在登录成功时调用该操作

答案 1 :(得分:0)

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;

这就是为什么当你在mwvm.CurrentViewModel方法中设置Login属性时,不会触发绑定。

因此,要实现您要执行的操作,您可以订阅MainWindowViewModel以登录成功消息并在那里设置当前的viewmodel。以下是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;
    }
});