WPF + DevExpress学习04 整合Prism+MVVM

安装包

	Prism.Unity 
	Prism.Wpf

MVVM登录功能

首先简单的说一下 MVVM 是一种数据驱动试图的模式 通过修改数据来触发界面上的变化,Prism.Unity 是一个IOC 容器框架

App.cs

// 首先继承 PrismApplication
 public partial class App : PrismApplication{
     // 主界面
    protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>;
        }
        // 初始化前的判断
	     protected override void InitializeShell(Window shell)
        {
            if (Container.Resolve<Login>().ShowDialog() == false)
            {
                Application.Current?.Shutdown();
            }
            else
            {
                base.InitializeShell(shell);
            }
        }
        // 容器注册服务的地方
       protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.Register<ILoginService, LoginService>();
            containerRegistry.RegisterScoped<DBContext>();
        }
 }

Login界面

<Window x:Class="NhxProjectSystem.Main.Views.Login"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NhxProjectSystem.Main.Views"
        mc:Ignorable="d"
        Name="loginWindow"
        WindowStartupLocation="CenterScreen"
        Title="登录" MaxHeight="450" MaxWidth="700" MinWidth="700" MinHeight="450" 
        ResizeMode="NoResize "
        xmlns:prism="http://prismlibrary.com/"
         prism:ViewModelLocator.AutoWireViewModel="True"
        >
    <Grid  >
        <DockPanel>
            <Image  Grid.Column="0" Source="/Image/LoginBg.png" Height="450" Width="400" />
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"   >
                <TextBlock Width="280" TextAlignment="Center" Padding="0,30,0,30" FontSize="27" LineHeight="30" >系统TextBlock>
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
                    <TextBlock Width="260"  >账号TextBlock>
                    <TextBox TextWrapping="Wrap"  Text="{Binding UserName,Mode=TwoWay}" Name="UserName"  Padding="0,5"  Margin="0,0,0,20" BorderBrush="#40a9ff" />
                    <TextBlock >密码TextBlock>
                    <TextBox TextWrapping="Wrap"   Text="{Binding Password,Mode=TwoWay}"  Name="Password"  Padding="0,5" Margin="0,0,0,20" />
                    <Button  Content="登 录"   Padding="0,5" CommandParameter="{Binding ElementName=loginWindow}"  Command="{Binding LoginCommand}" />
                StackPanel>
            StackPanel>
            
        DockPanel>
     

    Grid>
Window>

LoginViewModel.cs 登录

    public interface ILoginService
    {
        User UserLogin(string username, string password);
    }
      public class LoginService : ILoginService
    {
        [Dependency]  // using Unity;
        public DBContext _DBContext { get; set; }
        public User UserLogin(string username, string password)
        {
         return   _DBContext .NhxUsers.AsNoTracking().FirstOrDefault(c=>c.Password==password&&c.Account==username);
        }
    }
 public class LoginViewModel : BindableBase
    {
        [Dependency]  //属性注入;
        public ILoginService _loginService { get; set; }
        private string userName = "";
        private string password = "";
        public string UserName
        {
            get { return userName; }
            set { SetProperty(ref userName, value); }
        }
        public string Password
        {
            get { return password; }
            set { SetProperty(ref password, value); }
        }
        // 命令
        ICommand? loginCommand;
        public ICommand LoginCommand
        {
            get
            {
                if (loginCommand == null)
                {
                    loginCommand = new DelegateCommand<object>(UserLogin);
                }
                return loginCommand;
            }
        }
        void UserLogin(object obj)
        {
            var LoginUser=_loginService.UserLogin(this.UserName, this.Password);
            if (LoginUser == null)
            {
                MessageBox.Show("用户名或密码错误");
                return;
            }
      
            (obj as Window).DialogResult = true;
        }
    }
}

模块化开发

原本是准备按照正常的方式来实现 但是看了一些文章和实现方式发现了一种更好的更解耦的方式 中间踩了很多坑 记录一下
WPF + DevExpress学习04 整合Prism+MVVM_第1张图片
这是我的布局图 看似很简单 我当初实现的时候也是这样想的
现在要考虑三个问题 1 动态菜单 2 工具栏事件的消息订阅 我在每个独立的模块页面都可以监听 3 如何实现切换菜单 还要考虑模块化 话不多说直接上代码
先了解 RegionManager ,其次就是Prism 模块的加载机制
WPF + DevExpress学习04 整合Prism+MVVM_第2张图片
项目结构 模块内有两个界面 基础设置 和 甘特图界面

 public interface IView
    {
    }
    public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";

        //Region管理对象
        private IRegionManager _regionManager;
        private IModuleCatalog _moduleCatalog;
        private ObservableCollection<IModuleInfo> _modules;
        private DelegateCommand _loadModulesCommand;
        private DelegateCommand _openViewA;
        private DelegateCommand _openViewB;
        private DelegateCommand _goBackView;
        private DelegateCommand _goForwardView;
        private IModuleInfo _moduleInfo;

        //导航日志
        private IRegionNavigationJournal _navigationJournal;

        public IView View { get; set; }

        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public ObservableCollection<IModuleInfo> Modules
        {
            get => _modules ?? (_modules = new ObservableCollection<IModuleInfo>());
        }

        public DelegateCommand LoadModulesCommand { get => _loadModulesCommand = new DelegateCommand(InitModules); }

        public IModuleInfo ModuleInfo
        {
            get
            {
                return _moduleInfo;
            }

            set
            {
                _moduleInfo = value;
                Navigate(value);
            }
        }

        public DelegateCommand OpenViewA
        {
            get => _openViewA ?? (_openViewA = new DelegateCommand(OpenViewAAction));
        }

        public DelegateCommand OpenViewB
        {
            get => _openViewB ?? (_openViewB = new DelegateCommand(OpenViewBAction));
        }

        public DelegateCommand GoBackView { get => _goBackView ?? (_goBackView = new DelegateCommand(GoBackViewAction)); }

        public DelegateCommand GoForwardView { get => _goForwardView ?? (_goForwardView = new DelegateCommand(GoForwardViewAction)); }

        public MainWindowViewModel(IRegionManager regionManager, IModuleCatalog moduleCatalog)
        {
            _regionManager = regionManager;
            _moduleCatalog = moduleCatalog;
        }

        private void OpenViewAAction()
        {
            //_regionManager.RequestNavigate("ContentRegion", "TempViewA");

            _regionManager.RequestNavigate("ContentRegion", "TempViewA", arg =>
            {
                //记录导航日志上下文
                _navigationJournal = arg.Context.NavigationService.Journal;
            });
        }

        private void OpenViewBAction()
        {
            //_regionManager.RequestNavigate("ContentRegion", "TempViewB");

            _regionManager.RequestNavigate("ContentRegion", "TempViewB", arg =>
            {
                //记录导航日志上下文
                _navigationJournal = arg.Context.NavigationService.Journal;
            });
        }

        /// 
        /// 导航日志:导航到上一个
        /// 
        private void GoBackViewAction()
        {
            if (_navigationJournal.CanGoBack)
            {
                _navigationJournal.GoBack();
            }
        }

        /// 
        /// 导航日志:导航到下一个
        /// 
        private void GoForwardViewAction()
        {
            if (_navigationJournal.CanGoForward)
            {
                _navigationJournal.GoForward();
            }
        }

        public void InitModules()
        {
            //var dirModuleCatalog =;
            Modules.AddRange(_moduleCatalog.Modules);
        }

        private void Navigate(IModuleInfo info)
        {
            var paramete = new NavigationParameters();
            _regionManager.RequestNavigate("ContentRegion", $"{info.ModuleName}View", arg =>
            {
                //记录导航日志上下文
                _navigationJournal = arg.Context.NavigationService.Journal;
            });
          //  _regionManager.RequestNavigate("ContentRegion", $"{info.ModuleName}View", paramete);
        }
    }
<Window xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"  x:Class="NhxProjectSytem.Main.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/" 
        xmlns:dxa="http://schemas.devexpress.com/winfx/2008/xaml/accordion"
        prism:ViewModelLocator.AutoWireViewModel="True"

        Title="{Binding Title}" Height="350" Width="525" >
    <DockPanel>
        <dxdo:DockLayoutManager FloatingMode="Desktop" ClosedPanelsBarVisibility="Never">
            <dxdo:LayoutGroup Orientation="Horizontal">
                <dxdo:LayoutPanel Name="Navigation" Caption="导航"  AllowClose="False" ItemWidth="200">
                    <dxa:AccordionControl    ItemsSource="{Binding Modules}"     Name="Menus"  SelectedItem="{Binding ModuleInfo}" >
                        
                        <dxa:AccordionControl.ItemContainerStyle>
                            <Style TargetType="dxa:AccordionItem">
                                "Header" Value="{Binding ModuleName}"/>
                            Style>
                        dxa:AccordionControl.ItemContainerStyle>
                       
                    dxa:AccordionControl>
                dxdo:LayoutPanel>
                <dxdo:DocumentPanel  >
                    <ContentControl  prism:RegionManager.RegionName="ContentRegion"/>
                dxdo:DocumentPanel>
            dxdo:LayoutGroup>
            
        dxdo:DockLayoutManager>
    DockPanel>

Window>

App

 两种添加模块的方式
    public partial class App
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }
        //protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        //{
         
        //    // 1 添加模块
        //    moduleCatalog.AddModule();
        //    moduleCatalog.AddModule();
        //    base.ConfigureModuleCatalog(moduleCatalog);
        //}
        protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
        {
            base.ConfigureRegionAdapterMappings(regionAdapterMappings);
        }
        // 2
        protected override IModuleCatalog CreateModuleCatalog()
        {
            return new DirectoryModuleCatalog() { ModulePath = @".\" };  

        }
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
       
        }
    }

实例界面

// Module 这个特性只有在反射的时候才生效
[Module(ModuleName = "BasicSetting")]
    public class BasicSettingModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {
            var regionManager = containerProvider.Resolve<IRegionManager>();
            //通过ContentRegion管理导航默认初始页面ContactView
            var contentRegion = regionManager.Regions["ContentRegion"];
        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<BasicSettingView>();
        }
    }
     public class BasicSettingViewModel : BindableBase, INavigationAware
    {
        private string _message;
        public string Message
        {
            get { return _message; }
            set { SetProperty(ref _message, value); }
        }

        public BasicSettingViewModel()
        {
            Message = "View A from your Prism Module";
        }
        public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
        {
            bool result = true;

            // this is demo code only and not suitable for production. It is generally
            // poor practice to reference your UI in the view model. Use the Prism
            // IDialogService to help with this.
            if (MessageBox.Show("Do you to navigate?", "Navigate?", MessageBoxButton.YesNo) == MessageBoxResult.No)
                result = false;

            continuationCallback(result);
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            //是否创建新示例。为true的时候表示不创建新示例,页面还是之前的;如果为false,则创建新的页面。
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            //导航离开当前页面前。
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            //导航到当前页面前, 此处可以传递过来的参数以及是否允许导航等动作的控制。
        }
    }
····
简单 完成 这个模块不同方式卡我了将近两个小时 经过仔细排查和测试才发现这个坑 

你可能感兴趣的:(wpf,学习)