WPF单例启动及利用单例制作类似WORD打开文档选项卡效果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF单例启动及利用单例制作类似WORD打开文档选项卡效果相关的知识,希望对你有一定的参考价值。

文章目的如下:

1.WPF应用同时只允许运行一个实例

2.利用这个单例特性实现类似Word等多选项卡打开的效果

3.示例代码下载

废话不多说直接正题。

1.引用程度集 Microsoft.VisualBasic

2.移除App.XAML

3.创建类 MyWPFApp.cs 继承 System.Windows.Application 自定义一个 Application

    public class MyWPFApp : Application
    {
        public MyWPFApp()
        {
            ConfigApp();
        }

        public MyWPFApp(List<string> args)
        {
            this.OpenArgs = args;
            ConfigApp();
        }

        protected void ConfigApp()
        {
            this.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
        }

    }

2.创建类 SingleAppInsWrapper.cs 继承 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase 自定义一个包装类 this.IsSingleInstance = true

在重写 OnStartupNextInstance 中就可以处理当再有相同实例打开时的处理了(利用这个事件可扩展双击文件关联打开应用作出类似Office Word 打开多个文件选择卡的效果)

    /// <summary>
    /// 单例应用包装类
    /// </summary>
    public class SingleAppInsWrapper :Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
    {
        public SingleAppInsWrapper()
        {
            // 标记为单例应用
            this.IsSingleInstance = true;
        }

        private MyWPFApp _myWPFApp;

        protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
        {
            //手动加载WPF应用
            this._myWPFApp = new MyWPFApp(eventArgs.CommandLine.ToList());
            this._myWPFApp.Run();
            return false;
        }

        protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
        {
            //从这里实现当再有相同应用打开时的逻辑
        }
    }

3.添加 Startup.cs 类作为应用入口(到这步为止单例需要的基本完成)

    /// <summary>
    /// 启用应用类
    /// </summary>
    public class Startup
    {
        [STAThread]
        public static void Main(string[] args)
        {
            SingleAppInsWrapper wrapper = new SingleAppInsWrapper();
            wrapper.Run(args);
        }
    }

以下开始则为额外的扩展,制作一个双击文件打开应用展示文件,当应用已打开则在应用中添加新的选项卡打开文件,不关心这点的可以跳过。

4.修改 MainWindow.xaml 中内容为

<Window x:Class="WPF.SingleIns.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="5*"/>
            <RowDefinition Height="59*"/>
        </Grid.RowDefinitions>
        <TextBlock>
            可以设置一些可读取文件(例如.txt)的打开方式为本程序,双击文件则会在这里以Tab方式打开
        </TextBlock>
        <TabControl Name="tabContent" Grid.Row="1">
        </TabControl>
    </Grid>
</Window>

5.修改MainWindow.xaml.cs 为

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //若为命令打开,则打开参数中的文档
            var app = ((MyWPFApp)Application.Current);
            if (!string.IsNullOrEmpty(app.OpenFilePath))
                app.OpenDocWin(app.OpenFilePath);
        }

        public void SwitchOrAppendTab(string filepath)
        {
            if (!SwitchTab(filepath))
                AppendTab(filepath);
        }

        /// <summary>
        /// 切换选择卡
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        protected bool SwitchTab(string filepath)
        {
            TabItem selItem = null;
            foreach (TabItem item in this.tabContent.Items)
            {
                if ((string)item.Tag == filepath)
                    selItem = item;
            }

            if (selItem != null)
            {
                this.tabContent.SelectedItem = selItem;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 添加选项卡
        /// </summary>
        /// <param name="filepath"></param>
        protected void AppendTab(string filepath)
        {
            var tabContainer = (IAddChild)this.tabContent;

            TabItem tabItem = new TabItem();
            tabItem.Tag = filepath;
            tabItem.Header = System.IO.Path.GetFileName(filepath);
            tabItem.Content = System.IO.File.ReadAllText(filepath, Encoding.Default);

            tabContainer.AddChild(tabItem);

            //设置添加项为选中项
            this.tabContent.SelectedItem = tabItem;
            
        }
    }

6.MyWPFApp.cs 中添加方法

        public string OpenFilePath
        {
            get
            {
                if (OpenArgs.Count > 0)
                    return this.OpenArgs.First();
                return string.Empty;
            }
        }

        public void OpenDocWin(string filePath)
        {
            //这里的 MainWindow转换类型换成你的项目所在的命名空间
            var mainWin = (WPF.SingleIns.MainWindow)this.MainWindow;
            mainWin.SwitchOrAppendTab(filePath);
        }

7.SingleAppInsWrapper.cs 中的 OnStartupNextInstance内添加以下代码即可

        protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
        {
            var filepath = eventArgs.CommandLine.First();
            //从这里实现当再有相同应用打开时的逻辑
            this._myWPFApp.OpenDocWin(filepath);
        }

最终演示效果如下

技术分享

 

源码下载:

 https://files.cnblogs.com/files/nekoyzx/WPF.SingleIns.7z

以上是关于WPF单例启动及利用单例制作类似WORD打开文档选项卡效果的主要内容,如果未能解决你的问题,请参考以下文章

如何利用ASP生成WORD文档

如何在类扩展中添加静态(存储)属性以制作单例? (迅速)

单例模式

Java设计模式之《单例模式》及应用场景

跨进程加载的 DLL - 如何使某些操作“类似于单例”

请问如何利用宏在word中绘制表格,解决的问题是一个word原来是3列,现在想增加一列,想录一个宏