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

时间: 2024-10-12 23:28:18

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

单例模式(懒汉式单例、饿汉式单例、登记式单例)

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象. 注意: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 介绍 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点.

struts2的action是多例,servlet是单例

struts2中action是多例的,即一个session产生一个action如果是单例的话,若出现两个用户都修改一个对象的属性值,则会因为用户修改时间不同,两个用户访问得到的 属性不一样,操作得出的结果不一样.举个例子:有一块布长度300cm,能做一件上衣(用掉100cm)和一件裤子(用掉200cm);甲和乙同时访问得到的 长度都是300cm,甲想做上衣和裤子,他先截取100cm去做上衣,等上衣做完再去做裤子,而乙这时正好也拿100cm去做上衣,那 好,等甲做完上衣再做裤子的时候发现剩下的布(

设计模式中饿汉式单例类和懒汉式单例类

单例模式的特点为: *单例类只有一个实例. *单例类必须自己创建自己的唯一实例. *单例类必须给所有其他对象提供这一实例. 饿汉式单例类: 而饿汉式单例类则在java语言中是最为简单的单例类,这是一个描述饿汉式单例类的类图的实现. 此类图中,此类已经将自己实例化. 源码为: package singleton; public class EagerSingleton { private static EagerSingleton instance=new EagerSingleton(); /*

你研究过单例么?这样写单例效率最高.

首先,小汤我在这里,要表示一下歉意,本来是想要每天写一篇Swift的学习小tip的,无奈近期手头的money花差的差点儿相同了,仅仅能迫不得已,出门找工作去了,没能履行承诺之处还请大家见谅. 那么,废话不多说了,開始我们今天的主题: 单例 ! 单例介绍: 说到单例,大家应该都不陌生,在传说中的那23种 (为啥我就会6种捏o(╯□╰)o-) 设计模式中,单例应该是属于和简单工厂模式并列的最简单的设计模式了,也应该是最经常使用的. 像这样简单易懂,又能有效提高程序执行效率的设计模式,作为一个iOS程

Spring单例Bean中注入多例Bean

问题: 当在一个单例Bean中注入一个多例Bean的时候,是获取不到那个多例对象的,因为,单例在初始化的时候,就直接初始化,这个多例Bean啦, 一直获取的是第一次初始化的Bean 配置文件: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="htt

Scala 深入浅出实战经典 第79讲:单例深入讲解及单例背后的链式表达式

package com.parllay.scala.bestpractive import scala.reflect.runtime.universe import scala.reflect.runtime.universe.typeOf import com.parllay.scala.bestpractive.Scala /** * Created by richard on 15-9-5. * 第79讲:单例深入讲解及单例背后的链式表达式 */ object Scala class J

在InfoPath表单内提交表单并启动工作流

在InfoPath表单内提交表单并启动工作流 MOSS中对工作流的强大支持,让我们可以做很多应用. 举个例子,我们可以用表单库做审批表单,然后给这个表单库附加一个流程. 我们可能希望用户在填写表单的时候,在表单中填一些在启动工作流时需要用的信息,比如设置审批人等等. 我们的表单会像下面这样,包括待审批内容,和设置审批者等其他工作流设置. 我们也希望用户在点“保存”的时候,提交表单并同时根据用户设置的审批人来启动工作流. ( MOSS默认的模式是,提交完表单以后,在另一个页面启动工作流,需要做两步

利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe)

原文:利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe) 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了.这样交给用户很不方便,希望的效果是直接交付一个exe文件. 这时候就需要借助一款名为Fody.Costura的插件.Fody.Costura是一个Fody框架下的插件,可通过Nuget安装到VS工程中.安装之后,就可以将项目所依赖的DLL(甚至PDB)文件全部打包到EXE文件里. 使用 Costura

实验四 利用单臂路由实现VLAN间路由

[实验名称] 利用单臂路由实现VLAN间路由. [实验目的] 掌握如何在路由器上划分子接口.封装Dot1q(IEEE 802.1q)协议,实现VLAN间的路由. [需求分析] 需要在交换机上配置VLAN,然后在路由器连接交换机的端口上划分子接口,给相应的VLAN设置IP地址,以实现VLAN间的路由. [实验设备] 三层交换机一台. 路由器一台. [预备知识] 交换机的基本配置方法.VLAN的工作方法.Trunk的工原理和配制作原则和配置方法. [实验原理] 在交换网络中,通过VLAN对一个物理网