• Prism.WPF -- Prism框架使用(下)


    本文参考Prism官方示例

    命令使用

    Prism提供了两种命令:DelegateCommand和CompositeCommand。

    DelegateCommand

    DelegateCommand封装了两个委托:Execute和CanExecute,使用如下:

    // view
    <Button Command="{Binding ExecuteDelegateCommand}" Content="DelegateCommand"/>
    
    // viewmodel
    public DelegateCommand ExecuteDelegateCommand { get; private set; }
    
    public MainWindowViewModel()
    {
        ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);
    }
    
    private void Execute()
    {
        UpdateText = $"Updated: {DateTime.Now}";
    }
    
    private bool CanExecute()
    {
        return IsEnabled;
    }
    
    CompositeCommand

    CompositeCommand为复合命令,由多个子命令构成。当调用CompositeCommand时,将依次调用每个子命令。默认情况下,当所有子命令CanExecute均返回true时才会执行CompositeCommand。使用方法如下:

    // Project.Core中定义接口及实现
    public interface IApplicationCommands
    {
        CompositeCommand SaveCommand { get; }
    }
    
    public class ApplicationCommands : IApplicationCommands
    {
        private CompositeCommand _saveCommand = new CompositeCommand();
        public CompositeCommand SaveCommand
        {
            get { return _saveCommand; }
        }
    }
    
    // App.xaml.cs中注册单例对象
    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterSingleton<
            IApplicationCommands, ApplicationCommands>();
    }
    
    // viewmodel中添加子命令
    public TabViewModel(IApplicationCommands applicationCommands)
    {
        _applicationCommands = applicationCommands;
    
        UpdateCommand = new DelegateCommand(Update).ObservesCanExecute(
            () => CanUpdate);
    
        _applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
    }
    
    // view中执行命令(需在对应的viewmodel的构造函数中传入IApplicationCommands实例)
    <Button Content="Save" Command="{Binding ApplicationCommands.SaveCommand}"/>
    

    EventAggregator

    EventAggregator是一种事件机制,解决了松耦合模块间的通信问题。使用方法如下:

    // Project.core中声明事件类型
    public class MessageSentEvent : PubSubEvent<string>
    {
    }
    
    // viewmodel中发布事件
    IEventAggregator _ea;
    public MessageViewModel(IEventAggregator ea)
    {
        _ea = ea;
        // 发布事件的命令
        SendMessageCommand = new DelegateCommand(SendMessage);
    }
    
    private void SendMessage()
    {
        _ea.GetEvent<MessageSentEvent>().Publish(Message);
    }
    
    // viewmodel中订阅事件
    IEventAggregator _ea;
    public MessageListViewModel(IEventAggregator ea)
    {
        _ea = ea;
        _ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);
        // 如下方式可以过滤事件,可通过第二个参数指定处理线程
        // _ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived, 
            ThreadOption.PublisherThread, false, 
            (filter) => filter.Contains("Brian"));
    }
    
    private void MessageReceived(string message)
    {
        // hava a message
    }
    

    RegionNavigation

    区别于View Discovery和View Injection,RegionNavigation可通过region名称与要导航的视图名称实现更通用的视图导航功能,使用如下:

    // 模块类中注册导航视图
    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterForNavigation<ViewA>();
    }
    
    // xaml导航命令
    <Button Command="{Binding NavigateCommand}" CommandParameter="ViewA" >Navigate to View A</Button>
    
    // viewmodel实现导航
    public DelegateCommand<string> NavigateCommand { get; private set; }
    
    public MainWindowViewModel(IRegionManager regionManager)
    {
        _regionManager = regionManager;
        NavigateCommand = new DelegateCommand<string>(Navigate);
    }
    
    private void Navigate(string navigatePath)
    {
        if (navigatePath != null)
            _regionManager.RequestNavigate("ContentRegion", 
                navigatePath, NavigationCompleted);
    }
    
    // 可指定导航完成回调
    private void NavigationCompleted(NavigationResult result)
    {
        // ...
    }
    
    INavigationAware接口

    INavigationAware接口包含三个方法:OnNavigatedFrom、OnNavigatedTo、IsNavigationTarge。当ViewAViewModel及ViewBViewModel均实现了INavigationAware接口,ViewA导航到ViewB时,先调用ViewA的OnNavigatedFrom方法,然后调用ViewB的IsNavigationTarge,当其返回true时,调用OnNavigatedTo方法,若IsNavigationTarge返回false,创建新ViewB。示例如下:

    public class ViewAViewModel : BindableBase, INavigationAware
    {
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            // ...
        }
    
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }
    
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            // ...
        }
    }
    
    IConfirmNavigationRequest接口

    IConfirmNavigationRequest接口继承了INavigationAware接口,并添加了ConfirmNavigationRequest方法。若ViewAViewModel实现了IConfirmNavigationRequest接口,当ViewA导航到ViewB时,先调用ConfirmNavigationRequest方法,若continuationCallback()参数为true,将继续执行导航,执行OnNavigatedFrom方法;若continuationCallback()参数为false,停止导航。示例如下:

    public class ViewAViewModel : BindableBase, IConfirmNavigationRequest
    {
        public void ConfirmNavigationRequest(NavigationContext navigationContext, 
            Action<bool> continuationCallback)
        {
            bool result = true;
    
            if (MessageBox.Show("Do you to navigate?", "Navigate?", 
                MessageBoxButton.YesNo) == MessageBoxResult.No)
                result = false;
    
            continuationCallback(result);
        }
    
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }
    
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {  
        }
    
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
        }
    }
    
    IRegionMemberLifetime接口

    IRegionMemberLifetime接口只包含一个KeepAlive只读属性。其默认值为true,若其为false,则当该region导航到其它视图时,实现了该接口的当前视图将从IRegion.Views集合中移除并回收。若为true,即使导航到其它视图,该视图依然存在于IRegion.Views集合。示例如下:

    public class ViewAViewModel : BindableBase, IRegionMemberLifetime
    {
        public bool KeepAlive
        {
            get
            {
                return false;
            }
        }
    }
    
    参数传递

    可使用NavigationParameters实现导航时的参数传递,使用方法如下:

    // 导航命令
    private void PersonSelected(Person person)
    {
        var parameters = new NavigationParameters();
        parameters.Add("person", person);
    
        if (person != null)
            _regionManager.RequestNavigate("PersonDetailsRegion", 
                "PersonDetail", parameters);
    }
    
    // 参数处理
    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        var person = navigationContext.Parameters["person"] as Person;
        // ...
    }
    
    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
        var person = navigationContext.Parameters["person"] as Person;
        // ...
    }
    

    Navigation Journal可以记录导航的过程,其通过IRegionNavigationJournal接口实现。通过Navigation Journal,可以实现向前/向后导航。示例如下:

    // GoForward
    public class PersonListViewModel : BindableBase, INavigationAware
    {
        IRegionNavigationJournal _journal;
        public DelegateCommand GoForwardCommand { get; set; }
    
        public PersonListViewModel(IRegionManager regionManager)
        {
            ...
            GoForwardCommand = new DelegateCommand(GoForward, CanGoForward);
        }
    
        // IRegionNavigationJournal.GoBack到行至此
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            _journal = navigationContext.NavigationService.Journal;
            GoForwardCommand.RaiseCanExecuteChanged();
        }
    
        private void GoForward()
        {
            _journal.GoForward();
        }
    
        private bool CanGoForward()
        {
            return _journal != null && _journal.CanGoForward;
        }
    }
    
    // GoBack
    public class PersonDetailViewModel : BindableBase, INavigationAware
    {
        IRegionNavigationJournal _journal;
        public DelegateCommand GoBackCommand { get; set; }
    
        public PersonDetailViewModel()
        {
            GoBackCommand = new DelegateCommand(GoBack);
        }
    
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            _journal = navigationContext.NavigationService.Journal;
        }
    
        private void GoBack()
        {
            _journal.GoBack();
        }
    }
    

    InvokeCommandAction

    Prism提供了InvokeCommandAction以使ViewModel处理View的事件,示例如下:

    // view xaml
    <ListBox ItemsSource="{Binding Items}" SelectionMode="Single">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <prism:InvokeCommandAction Command="{Binding SelectedCommand}" 
                    TriggerParameterPath="AddedItems" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ListBox>
    
    // viewmodel
    public DelegateCommand<object[]> SelectedCommand { get; private set; }
    
    public MainWindowViewModel()
    {
        ...
        SelectedCommand = new DelegateCommand<object[]>(OnItemSelected);
    }
    
    private void OnItemSelected(object[] selectedItems)
    {
        if (selectedItems != null && selectedItems.Count() > 0)
            SelectedItemText = selectedItems.FirstOrDefault().ToString();
    }
    
    转载请注明出处,欢迎交流。
  • 相关阅读:
    trap命令
    MySQL数据库中日期中包涵零值的问题
    MySQL锁等待分析【2】
    MySQL锁等待分析【1】
    mysql日志文件相关的配置【2】
    mysql日志文件相关的配置【1】
    Linux的标准输出、标准错误输出、nohup
    mysql在关闭时的几个阶段
    MHA环境搭建【4】manager相关依赖的解决
    keepalived+httpd 做web服务的高可用
  • 原文地址:https://www.cnblogs.com/louzixl/p/14423836.html
Copyright © 2020-2023  润新知