Caliburn微型内容控件导航

问题描述 投票:0回答:2

我正在为此项目使用caliburn micro。我的ShellView带有contentcontrol:

<ContentControl x:Name="ActiveItem"
                        Grid.Row="0" Grid.Column="0" />

在ShellViewModel中,我用它来显示我的用户控件LoginView:

 public class ShellViewModel : Conductor<object>
    {
        public ShellViewModel()
        {
            ActivateItem(new LoginViewModel());
        }

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

但是,我无法使用我的按钮从LoginView导航到SignUpView:

<!-- Row 4 -->
<Button x:Name="ShowSignUp"
        Content="Sign Up Now!"
        Grid.Row="3" Grid.Column="1"
        Style="{StaticResource LoginBtnsStyle}" />

从ShellViewModel派生的LoginViewModel:

public class LoginViewModel : ShellViewModel
    {

    }

如何使用LoginView上的按钮从LoginView导航到SignUpView?我没有任何错误,只是没有改变视图。我还尝试将ShowSignUp()放在LoginViewModel上,但没有成功。

wpf mvvm caliburn.micro
2个回答
0
投票

您可以使用EventAggregator通过将指示性消息从LoginViewModel发布到ShellViewModel来更新UI来实现。

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

public class ActionInvokedMessage
    {
        public Screen Page { get; set; }
    }

Page属性将指示需要加载哪个屏幕。现在,您可以按以下方式更改LoginViewModel。

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());
        }


    }

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


0
投票

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

interface INavigation {
    void NavigateTo(System.Type typeId);
}

class ShellViewModel: Conductor<object>,  INavigation  {

    private List<object> pages = new List<Object>();

    public ShellViewModel() {
        pages.Add(new SignupViewModel(this));
        pages.Add(new LoginViewModel(this));
    }

    void NavigateTo(System.Type typeId) {
        var page = pages.Where(x => x.GetType() == typeId).FirstOrDefault()
        ActivateItem(page);
    }
}

class SignupViewModel {
    public SignupViewModel(INavigation navigation) {
        this.ShowLoginCommand= new NavigateCommand<LoginViewModel>(navigation);
    }
}

class LoginViewModel {
    public LoginViewModel (INavigation navigation) {
        this.ShowSignUpCommand = new NavigateCommand<SignupViewModel>(navigation);
    }
}

导航命令可以如下实现:

public class NavigateCommand<T> : ICommand
{
    public event EventHandler CanExecuteChanged;
    private readonly INavigation navigation;

    public NavigateCommand(INavigation navigation)
    {
        this.navigation = navigation;
    }

    public bool CanExecute(object parameter) => true;
    public void Execute(object parameter) => this.navigation.NavigateTo(typeof(T));
}

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

© www.soinside.com 2019 - 2024. All rights reserved.