Wpf Caliburn微内容控制导航

Wpf Caliburn微内容控制导航,wpf,mvvm,caliburn.micro,Wpf,Mvvm,Caliburn.micro,我在用caliburn micro做这个项目。 我有带contentcontrol的ShellView: <ContentControl x:Name="ActiveItem" Grid.Row="0" Grid.Column="0" /> 如何使用LoginView上的按钮从LoginView导航到SignUpView? 我没有收到任何错误,只是没有改变视图。 我还尝试将ShowSignUp()放在LoginView模型上,但没有成

我在用caliburn micro做这个项目。 我有带contentcontrol的ShellView:

<ContentControl x:Name="ActiveItem"
                        Grid.Row="0" Grid.Column="0" />
如何使用LoginView上的按钮从LoginView导航到SignUpView? 我没有收到任何错误,只是没有改变视图。 我还尝试将ShowSignUp()放在LoginView模型上,但没有成功

更新1ShellViewModel:

public class LoginViewModel : ShellViewModel
    {

    }
public class ShellViewModel : Conductor<object>, IHandle<ActionInvokedMessage>
    {
        DispatcherTimer dt = new DispatcherTimer();
        private SplashScreenViewModel _splashVM;
        private LoginViewModel _loginVM;
        private SignUpViewModel _signUpVM;
        private IEventAggregator _eventAggregator;

        public ShellViewModel(SplashScreenViewModel splashVM, LoginViewModel loginVM, SignUpViewModel signUpVM)
        {
            _loginVM = loginVM;
            _signUpVM = signUpVM;
            _splashVM = splashVM;
            ActivateItem(_splashVM);

            dt.Tick += new EventHandler(Dt_Tick);
            dt.Interval = new TimeSpan(0, 0, 2);
            dt.Start();
        }

        private void Dt_Tick(object sender, EventArgs e)
        {
            dt.Stop();
            ActivateItem(_loginVM);
        }

        public ShellViewModel(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;
            _eventAggregator.Subscribe(this);
            ActivateItem(new LoginViewModel(_eventAggregator));
        }

        public void Handle(ActionInvokedMessage message)
        {
            ActivateItem(message.Page);
        }

        public void ShowSignUp()
        {
            ActivateItem(new SignUpViewModel());
        }



    }
公共类ShellViewModel:导体,IHandle
{
Dispatchermer dt=新Dispatchermer();
私有SplashScreenViewModel\u splashVM;
private LoginViewModel_loginVM;
私有注册视图模型_signUpVM;
私人事件聚合器;
公共ShellViewModel(SplashScreenViewModel splashVM、LoginViewModel loginVM、SignUpViewModel signUpVM)
{
_loginVM=loginVM;
_signUpVM=signUpVM;
_splashVM=splashVM;
激活物(_splashVM);
dt.Tick+=新事件处理程序(dt_Tick);
dt.Interval=新的时间跨度(0,0,2);
dt.Start();
}
私有void Dt_Tick(对象发送方,事件参数e)
{
dt.Stop();
激活项(_loginVM);
}
公共ShellViewModel(IEventAggregator事件聚合器)
{
_eventAggregator=eventAggregator;
_eventAggregator.Subscribe(此);
ActivateItem(新的LoginView模型(_eventAggregator));
}
公共无效句柄(ActionInvokedMessage消息)
{
激活项(message.Page);
}
公开作废登记()
{
ActivateItem(新的SignUpViewModel());
}
}

您可以使用将指示消息从LoginViewModel发布到ShellViewModel以更新UI来实现这一点

首先,您需要定义一个消息类,它将告诉ShellViewModel需要更改哪个ViewModel。比如说,

public class ActionInvokedMessage
    {
        public Screen Page { get; set; }
    }
Page属性将指示需要加载的屏幕。现在,您可以如下更改您的LoginView模型

public class LoginViewModel: Screen
    {
        private IEventAggregator _eventAggregator;
        public LoginViewModel(IEventAggregator eventAggregator)
        {

            _eventAggregator = eventAggregator;
            _eventAggregator.Subscribe(this);
        }

        public void ShowSignUp()
        {
            _eventAggregator.PublishOnUIThread(new ActionInvokedMessage { Page = new SignupViewModel() }); ;
        }
    }
PublishOnUIThread方法将向消息类型为ActionInvokedMessage的所有侦听器广播一条消息以进行更改。下一步是确保ShellViewModel将侦听更改

public class ShellViewModel : Conductor<object>, IHandle<ActionInvokedMessage>
    {
        private IEventAggregator _eventAggregator;
        public ShellViewModel(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;
            _eventAggregator.Subscribe(this);
            ActivateItem(new LoginViewModel(_eventAggregator));
        }

        public void Handle(ActionInvokedMessage message)
        {
            ActivateItem(message.Page);
        }

        public void ShowSignUp()
        {
            ActivateItem(new SignupViewModel());
        }


    }
公共类ShellViewModel:导体,IHandle
{
私人事件聚合器;
公共ShellViewModel(IEventAggregator事件聚合器)
{
_eventAggregator=eventAggregator;
_eventAggregator.Subscribe(此);
ActivateItem(新的LoginView模型(_eventAggregator));
}
公共无效句柄(ActionInvokedMessage消息)
{
激活项(message.Page);
}
公开作废登记()
{
ActivateItem(新的SignupViewModel());
}
}

IHandle接口的实现允许我们处理ShellViewModel接收ActionInvokedMessage时需要执行的操作。正如代码中所示,这将是使用ActivateItem方法加载注册页面的合适位置。

您可以创建一个导航界面,并在视图模型中使用它来导航应用程序

接口失活{
无效导航到(System.Type typeId);
}
类别ShellViewModel:导体,无电{
私有列表页=新列表();
公共ShellViewModel(){
添加(新的SignupViewModel(此));
添加(新登录视图模型(本));
}
无效导航到(System.Type typeId){
var page=pages.Where(x=>x.GetType()==typeId).FirstOrDefault()
激活体(第页);
}
}
类注册视图模型{
公共注册视图模型(INavigation导航){
this.ShowLoginCommand=新导航命令(导航);
}
}
类LoginViewModel{
公共登录视图模型(iVigation导航){
this.ShowSignUpCommand=新导航命令(导航);
}
}
导航命令的实现方式如下:

public类导航命令:ICommand
{
公共事件处理程序CanExecuteChanged;
私人只读导航;
公共导航命令(导航导航)
{
这个.导航=导航;
}
public bool CanExecute(对象参数)=>true;
public void Execute(object参数)=>this.navigation.NavigateTo(typeof(T));
}

这里我传递System.Type,但您可以设计更好地描述导航请求的类型,以便可以传递其他参数。

我得到System.nullreferenceexception:对象引用未设置为对象的实例。在
public void ShowSignUp(){u eventAggregator.PublishOnUIThread(new ActionInvokedMessage{Page=new SignUpViewModel()});}
@Martin你能检查一下{u eventAggregator是否初始化了吗?@Martin你能调试一下,如果它不是{u eventAggregator.PublishOnUIThread(new ActionInvokedMessage Page=new SignUpViewModel());吗_eventAggregator为空。@这就是原因。你需要初始化它。您可以在构造函数中这样做,如上面的代码所示。
public class LoginViewModel: Screen
    {
        private IEventAggregator _eventAggregator;
        public LoginViewModel(IEventAggregator eventAggregator)
        {

            _eventAggregator = eventAggregator;
            _eventAggregator.Subscribe(this);
        }

        public void ShowSignUp()
        {
            _eventAggregator.PublishOnUIThread(new ActionInvokedMessage { Page = new SignupViewModel() }); ;
        }
    }
public class ShellViewModel : Conductor<object>, IHandle<ActionInvokedMessage>
    {
        private IEventAggregator _eventAggregator;
        public ShellViewModel(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;
            _eventAggregator.Subscribe(this);
            ActivateItem(new LoginViewModel(_eventAggregator));
        }

        public void Handle(ActionInvokedMessage message)
        {
            ActivateItem(message.Page);
        }

        public void ShowSignUp()
        {
            ActivateItem(new SignupViewModel());
        }


    }