C# WPF Prsim PrsimOutlook学习记录(一)

最近在学习 Prsim 和WPF,在油管上找到了一个 PrsimOutlook 项目,作者是 Brian Lagunas ,是当年 Prsim 搬家到GitHub时交给社区的三位贡献者之一.

照着视频学习加上有源代码,作者就是Prsim的作者之一,对Prsim相当的了解.

相关链接

视频一 Setting up the Prism Project 学习记录

视频一 程序最后的结果是这样的
在这里插入图片描述

使用 Prsim 提供的扩展创建模板,使用此模板可以快速创建 Prsim项目和 Prsim Module

PrsimOutlook 是 Prsim WPF项目的空模板
Modules 目录下三个项目是 Prsim WPF Mudule 的空模板
PrsimOutlook.Core 是用来放 共享的一些的基础设施

创建程序目录结构如下

在这里插入图片描述

  • PrsimOutlook 是 Prsim WPF项目的空模板
  • Modules 目录下三个项目是 Prsim WPF Mudule 的空模板
  • PrsimOutlook.Core 是用来放 共享的一些的基础设施
窗体分为3个Region,定义在 PrismOutlook.Core.RegionNames 类中
namespace PrismOutlook.Core
{
    public static class RegionNames
    {
        public static string ContentRegion = "ContentRegion";
        public static string OutlookGroupRegion = "OutlookGroupRegion";
        public static string RibbonRegion = "RibbonRegion";
    }
}

在MainWindow.xaml中 使用这3个 Region
<ig:RibbonWindowContentHost>
    <ig:RibbonWindowContentHost.Ribbon>
        <ig:XamRibbon prism:RegionManager.RegionName="{x:Static core:RegionNames.RibbonRegion}">
            
        </ig:XamRibbon>
    </ig:RibbonWindowContentHost.Ribbon>

    <DockPanel LastChildFill="True">

        <ig:XamOutlookBar prism:RegionManager.RegionName="{x:Static core:RegionNames.OutlookGroupRegion}" DockPanel.Dock="Left" Width="200"></ig:XamOutlookBar>

        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.ContentRegion}" />
    </DockPanel>

</ig:RibbonWindowContentHost>

最上方是 RibbonRegion ,左下侧是 OutlookGroupRegion,右侧是 ContentRegion

具体Region的内容,写在 Module中,这样可以降低耦合

首先将 PrsimOutlook 和Module 中的View 关联起来

这需要在App.xaml.cs override ConfigureModuleCatalog函数 添加 Module

 protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
 {
     moduleCatalog.AddModule<MailModule>();
     moduleCatalog.AddModule<ContactsModule>();
 }

其次需要在 MailModule.cs 和 ContactsModule.cs 中 将View 注册到视图上

由于Prsim有Unity,可以在通过这种方式获得 IRegionManager 的实例

		private readonly IRegionManager _regionManager;

        public MailModule(IRegionManager regionManager)
        {
            _regionManager = regionManager;   
        }

MailModule

namespace PrismOutlook.Modules.Mail
{
    public class MailModule : IModule
    {
        private readonly IRegionManager _regionManager;

        public MailModule(IRegionManager regionManager)
        {
            _regionManager = regionManager;   
        }

        public void OnInitialized(IContainerProvider containerProvider)
        {
            //TODO: remove
            _regionManager.RegisterViewWithRegion(RegionNames.ContentRegion, typeof(ViewA));


            _regionManager.RegisterViewWithRegion(RegionNames.RibbonRegion, typeof(HomeTab));
            _regionManager.RegisterViewWithRegion(RegionNames.OutlookGroupRegion, typeof(MailGroup));
        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            
        }
    }
}

ContactsModule

namespace PrismOutlook.Modules.Contacts
{
    public class ContactsModule : IModule
    {
        private readonly IRegionManager _regionManager;

        public ContactsModule(IRegionManager regionManager)
        {
            _regionManager = regionManager;
        }

        public void OnInitialized(IContainerProvider containerProvider)
        {
            _regionManager.RegisterViewWithRegion(RegionNames.OutlookGroupRegion, typeof(ContactsGroup));
        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            
        }
    }
}

这里面发现
ViewA 已经创建了,但 HomeTab , ContactsGroup , MailGroup 还没创建

MailGroup和 ContactsGroup 是注册到 OutlookGroupRegion
HomeTab 是注册到 RibbonRegion

现在要创建 MailGroup View

<ig:OutlookBarGroup x:Class="PrismOutlook.Modules.Mail.Menus.MailGroup"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:PrismOutlook.Modules.Mail.Menus"
             xmlns:ig="http://schemas.infragistics.com/xaml/wpf"
                    Header="Mail">
    <Grid>
        <TextBlock Text="Testing"/>
    </Grid>
</ig:OutlookBarGroup>

窗体类型是 OutlookBarGroup

现在创建 ContactsGroup

<ig:OutlookBarGroup x:Class="PrismOutlook.Modules.Contacts.Menus.ContactsGroup"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:PrismOutlook.Modules.Contacts.Menus"
             xmlns:ig="http://schemas.infragistics.com/xaml/wpf"
                    Header="Contacts">
    <Grid>
        <TextBlock Text="Tetsing again from Contacts" />
    </Grid>
</ig:OutlookBarGroup>

窗体类型也是 OutlookBarGroup

这里面有一个需要注意的地方,让我们回到 MainWindow.xaml

<ig:RibbonWindowContentHost>
    <ig:RibbonWindowContentHost.Ribbon>
        <ig:XamRibbon prism:RegionManager.RegionName="{x:Static core:RegionNames.RibbonRegion}">
            
        </ig:XamRibbon>
    </ig:RibbonWindowContentHost.Ribbon>

    <DockPanel LastChildFill="True">

        <ig:XamOutlookBar prism:RegionManager.RegionName="{x:Static core:RegionNames.OutlookGroupRegion}" DockPanel.Dock="Left" Width="200"></ig:XamOutlookBar>

        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.ContentRegion}" />
    </DockPanel>

</ig:RibbonWindowContentHost>

Prsim 对于 ContentControl,可以自动的将View 注入到 Region中
但对于其他的控件,需要自己写 RegionAdapter
所以对于 XamOutlookBar 需要写 XamOutlookBar 控件的 RegionAdapter
对于这个 RegionAdapter 我还不清楚是怎么写的,好在我们有源码,直接copy过来看看

using Infragistics.Windows.OutlookBar;
using Prism.Regions;

namespace PrismOutlook.Core.Regions
{
    public class XamOutlookBarRegionAdapter : RegionAdapterBase<XamOutlookBar>
    {
        public XamOutlookBarRegionAdapter(IRegionBehaviorFactory factory)
            : base(factory)
        {

        }

        protected override void Adapt(IRegion region, XamOutlookBar regionTarget)
        {
            region.Views.CollectionChanged += ((x, y) =>
            {
                switch (y.Action)
                {
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                        {
                            foreach (OutlookBarGroup group in y.NewItems)
                            {
                                regionTarget.Groups.Add(group);

                                //The WPF XamOutlookBar does not automatically select the first group in it's collection.
                                //So we must manually select the group if it is the first one in the collection, but we don't
                                //want to excute this code every time a new group is added, only if the first group is the current group being added.
                                if (regionTarget.Groups[0] == group)
                                {
                                    regionTarget.SelectedGroup = group;
                                }
                            }
                            break;
                        }
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                        {
                            foreach (OutlookBarGroup group in y.OldItems)
                            {
                                regionTarget.Groups.Remove(group);
                            }
                            break;
                        }
                }
            });
        }

        protected override IRegion CreateRegion()
        {
            return new SingleActiveRegion();
        }
    }
}

一顿操作猛如虎,大意就是 往 XamOutlookBar 加入Region
对于这个项目来说也就是 往 XamOutlookBar 加入 MailGroup 和 ContactsGroup

同时还需要写 XamRibbonRegionAdapter
代码如下

using Infragistics.Windows.Ribbon;
using Prism.Regions;
using System;
using System.Collections.Specialized;

namespace PrismOutlook.Core.Regions
{
    public class XamRibbonRegionAdapter : RegionAdapterBase<XamRibbon>
    {
        public XamRibbonRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
            : base(regionBehaviorFactory)
        {
        }

        protected override void Adapt(IRegion region, XamRibbon regionTarget)
        {
            if (region == null) throw new ArgumentNullException(nameof(region));
            if (regionTarget == null) throw new ArgumentNullException(nameof(regionTarget));

            region.Views.CollectionChanged += (s, e) =>
            {
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    foreach (var view in e.NewItems)
                    {
                        AddViewToRegion(view, regionTarget);
                    }

                }
                else if (e.Action == NotifyCollectionChangedAction.Remove)
                {
                    foreach (var view in e.OldItems)
                    {
                        RemoveViewFromRegion(view, regionTarget);
                    }
                }
            };
        }

        protected override IRegion CreateRegion()
        {
            return new SingleActiveRegion();
        }

        static void AddViewToRegion(object view, XamRibbon xamRibbon)
        {
            if (view is RibbonTabItem ribbonTabItem)
            {
                xamRibbon.Tabs.Add(ribbonTabItem);
            }
        }

        static void RemoveViewFromRegion(object view, XamRibbon xamRibbon)
        {
            if (view is RibbonTabItem ribbonTabItem)
            {
                xamRibbon.Tabs.Remove(ribbonTabItem);
            }
        }
    }
}

然后还需要在 App.xaml.cs 中 告诉 Prsim 一下,注册一下

 protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
 {
     base.ConfigureRegionAdapterMappings(regionAdapterMappings);
     regionAdapterMappings.RegisterMapping(typeof(XamOutlookBar), Container.Resolve<XamOutlookBarRegionAdapter>());
     regionAdapterMappings.RegisterMapping(typeof(XamRibbon), Container.Resolve<XamRibbonRegionAdapter>());
 }
总结

一路写下来,思路一下清晰了起来,照着视频学的时候还是一片懵懂,我会坚持写下去的

视频一 主要是把 程序框架搭了起来,将Module注册到了 MainWindow中,这样 程序就知道了各个Module.
然后将 View 通过 RegisterViewWithRegion 注册到 各个Region中.
Prsim 是有Unity的,所以程序可以使用依赖注入的方式,很方便
对于 ContentControl,Prsim 为我们提供了默认的方式 将View 注册到Region中
但对于 其他的控件,就需要自己来写 RegionAdapter,同时还需要在 ConfigureRegionAdapterMappings中注册一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值