一个简单的例子就是大家在使用很多应用程序,例如在使用Microsoft Word 时会遇到一种情况,不管你打开多少个文档,系统一次只能加载一个winword.exe 实例。当打开新文档时,文档在新窗口显示,但是始终只有一个应用程序控制所有文档窗口;如:可以提供平铺当前所有文档中相邻窗口的文档的特性。

  对于创建单实例的应用程序,WPF本身没有提供自带的解决方法,但可以通过变通的方式来实现——思路是当触发ApplicationStartup事件时,检查另一个实例是否在运行。方法是通过使用全局的mutex对像(mutex是操做系统中提供的用于进程间通信的同步方法)。虽然简单,但功能有限,如新实例无法与已经存在的实例进行通信。尤其是对于基于文档的用于程序而言,这确实是一个问题,如果新实例需要告诉已经存在的实例打开一个新的文档或者该文档是通过命令行参数传递的情况,那该使用什么方法来解决问题呢??

  WPF团队推荐我们一种最简单的方法就是:使用Windows  窗体提供的内置支持,该内置支持最初是用于VisualBasic 应用程序的,使用Window窗体和VisualBasic 的这一特新来开发基于C#的WPF程序会存在一个新旧应用程序之分,本质上旧式应用程序充当了WPF应用程序的封装器。流程是:当启动程序时将创建旧式应用程序,旧式应用程序接着创建WPF应用程序,旧式应用程序处理实例管理,而WPF应用程序处理正真的应用。

  下面我们通过一个实例来演示创建单实例应用程序的具体步骤:

一.创建WPF窗体项目,并添加Microsoft.VisualBasic.dll 引用。

二.首先创建一个Document.xaml,和 DocumentList.xaml 窗口文件,使用定义的类DocumentReference 表示对Document引用。

DocumentReference :

 public class DocumentReference
{
private Document document;
public Document Document
{
get { return document; }
set { document = value; }
} private string name;
public string Name
{
get { return name; }
set { name = value; }
} public DocumentReference(Document document, string name)
{
Document = document;
Name = name;
}
}

Document.LoadFile() 通过文件名读取文档内容,Document.OnClosed() 事件在文档窗体关闭时触发,用于从动态集合移除实例。

 public partial class Document : Window
{
private DocumentReference docRef; public Document()
{
InitializeComponent();
} public void LoadFile(DocumentReference docRef)
{
this.docRef = docRef;
this.Content = File.ReadAllText(docRef.Name);
this.Title = docRef.Name;
} protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
((WpfApp)Application.Current).Documents.Remove(docRef);
} }

DocumentList 窗体放置一个 <ListBox Name="lstDocuments"></ListBox> 的 lstDocuments控件,用于显示当前文档列表。

 public partial class DocumentList : Window
{
public DocumentList()
{
InitializeComponent(); lstDocuments.DisplayMemberPath = "Name";
lstDocuments.ItemsSource = ((WpfApp)Application.Current).Documents;
}
}

三.接着创建一个自定义的WPF类WpfApp.cs,该类继承于Windows.Application。在这里每当通过命令行参数传递给SingleInstanceApplication 类文件名时,会触发 SingleInstanceApplication 类的 OnStartupNextInstance 方法,并调用自定义的 ShowDocument() 方法为指定的文档加载文档窗体。

WpfApp:

  public class WpfApp : Application
{
private ObservableCollection<DocumentReference> documents =
new ObservableCollection<DocumentReference>();
public ObservableCollection<DocumentReference> Documents
{
get { return documents; }
set { documents = value; }
} protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
//WpfApp.Current = this; DocumentList list = new DocumentList();
this.MainWindow = list;
list.Show(); // Load the document that was specified as an argument.
if (e.Args.Length > ) ShowDocument(e.Args[]); } public void ShowDocument(string fileName)
{
try
{
Document doc = new Document();
DocumentReference docRef = new DocumentReference(doc, fileName);
doc.LoadFile(docRef);
doc.Owner = this.MainWindow;
doc.Show();
doc.Activate();
Documents.Add(docRef);
}
catch
{
MessageBox.Show("Could not load document.");
}
}
}

  四.创建继承于WindowsFormsApplicationBase 的自定义类 SingleInstanceApplication.cs 该类将提供3个用于管理实例的重要成员。

  • IsSingleInstance 用于确定此应用程序是否为单实例应用程序,在构造函数中设置值为true。
  • 重写 OnStartup(),程序启动时,重写该方法并创建WPF应用程序对象。
  • 重写 OnStartupNextInstance(),当另一个应用程序启动时触发该方法,该方法提供了访问命令行的参数的功能。此时可以调用WPF应用程序类的方法来创建窗口,但不能创建另一个应用程序对象。

SingleInstanceApplication:

 public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private WpfApp App;
public SingleInstanceApplication()
{
this.IsSingleInstance = true;
} protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
{
string extension = ".testDoc";
string title = "SingleInstanceApplication";
string extensionDescription = "A Test Document"; //return base.OnStartup(eventArgs);
App = new WpfApp();
App.Run();
return false;
} protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
//base.OnStartupNextInstance(eventArgs);
if (eventArgs.CommandLine.Count > )
App.ShowDocument(eventArgs.CommandLine[]);
}
}

五. 由于应用程序需要在APP类之前就要创建SingleInstanceApplication 类,所以这里就需要同过传统的Main方法作为启动入口。

 public class Startup
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceApplication wrapper = new SingleInstanceApplication();
wrapper.Run(args);
}
}

 六,为了测试单例程序,需要使用Window文件扩展名与程序相关联,将其文件类型注册。运行结果如下:

使用 WPF 创建单实例应用程序的更多相关文章

  1. WPF学习笔记 - 如何用WPF创建单实例应用程序

    使用一个已命名的(操作系统范围的)互斥量. bool mutexIsNew; using(System.Threading.Mutex m = new System.Threading.Mulex(t ...

  2. WPF点滴(2) 创建单实例应用程序

    最近有同事问道在应用程序启动之后,再次双击应用程序,如何保证不再启动新的应用程序,而是弹出之前已经启动的进程,本质上这就是创建一个单实例的WPF应用程序.在VS的工程树中有一个App.xaml和App ...

  3. WPF 单实例应用程序

    例如:Microsoft Word,不管打开多少个文档(也不管它们是如何打开的),一次只能加载 winword.exe 一个实例. 这便是单实例应用程序. 对于这种单实例应用程序,WPF 本身并未提供 ...

  4. [WPF]WPF设置单实例启动

    WPF设置单实例启动 使用Mutex设置单实例启动 using System; using System.Threading; using System.Windows; namespace Test ...

  5. WPF使用Mutex创建单实例程序失效

    vs2019 1.引入名称空间 using System.Threading; using System.Runtime.InteropServices; 2.导入dll并声明方法 [DllImpor ...

  6. Oracle - 给rac创建单实例dg,并做主从切换

    一.概述 本文将介绍如何给rac搭建单节点的dg,以及如何对其进行角色转换.预先具备的知识(rac搭建,单实例-单实例dg搭建) 二.实验环境介绍 主库rac(已安装rac,并已有数据库orcl)ra ...

  7. 关于struts和Spring 结合到一起之后存在ACtion创建单实例还是多

    struts 2的Action是多实例的并非单例,也就是每次请求产生一个Action的对象.原因是:struts 2的Action中包含数据,例如你在页面填写的数据就会包含在Action的成员变量里面 ...

  8. C# 实现单实例程序

    在我们经常使用的软件中,当我们已经打开后,再次打开时,有的软件不会出现两个.例如有道词典,会将上次的界面显示出来,或者提示我们“该程序已经运行...”.我通过一个简单的C# WPF例子来说明. 首先我 ...

  9. DevExpress Winform使用单例运行程序方法和非DevExpress使用Mutex实现程序单实例运行且运行则激活窗体的方法

    原文:DevExpress Winform使用单例运行程序方法和非DevExpress使用Mutex实现程序单实例运行且运行则激活窗体的方法 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA ...

随机推荐

  1. 【iOS开发-71】解决方式:Attempting to badge the application icon but haven&#39;t received permission from the...

    (1)原因 一切都是iOS8捣的鬼.您假设把模拟器换成iOS7.1或者更早的,就不会有这个问题.而如今在iOS8中要实现badge.alert和sound等都需要用户允许才干,由于这些都算做Notif ...

  2. Visual Assist X 10.8.2052的Crack破解补丁. 2014.11.05 (General release.)

    VA小组立即更新频率似有些放缓几乎,版本号都是2个月才更新一次,而这次的更新幅度也还是比較大的,新增了6个特性,而且修正和20余处大大小小的问题,而且也是正式发行版,推荐更新. 对于破解补丁还是老规矩 ...

  3. SecureCRT 连接虚拟机Linux

    SecureCRT 连接虚拟机Linux   最近在学习linux,在学习中遇到了一些问题,现总结一下. 虚拟机我用的是VirtualBox,完美支持中文,可以在电脑中创建虚拟机环境,上手非常简单.具 ...

  4. 盒子游戏(The Seventh Hunan Collegiate Programming Contest)

    盒子游戏 有两个相同的盒子,其中一个装了n个球,另一个装了一个球.Alice和Bob发明了一个游戏,规则如下:Alice和Bob轮流操作,Alice先操作.每次操作时,游戏者先看看哪个盒子里的球的数目 ...

  5. WPF案例 (四) 模拟Windows7桌面任务栏

    原文:WPF案例 (四) 模拟Windows7桌面任务栏 这个程序模彷了Windows7的桌面任务栏,当在桌面上双击某个快捷方式时,将打开一个新的子界面,并且在任务栏里创建一个链接到此界面的任务栏图标 ...

  6. poj3206(bfs+最小生成树)

    传送门:Borg Maze 题意:有一个迷宫,里面有一些外星人,外星人用字母A表示,#表示墙,不能走,空格可以走,从S点出发,在起点S和A处可以分叉走,问找到所有的外星人的最短路径是多少? 分析:分别 ...

  7. hdu 4739【位运算】.cpp

    题意: 给出n个地雷所在位置,正好能够组成正方形的地雷就可以拿走..为了简化题目,只考虑平行于横轴的正方形.. 问最多可以拿走多少个正方形.. 思路: 先找出可以组成正方形的地雷组合cnt个.. 然后 ...

  8. C#操作Cookie

    /* 创建者:菜刀居士的博客  * 创建日期: 2014年09月02号  * 功能:操作Cookie  *  */ namespace Net.String.ConsoleApplication { ...

  9. solr4.9r+ Eclipse 4.3+ tomcat 7.5 +winds7(二)

    尊重原创,原文地址:http://blog.csdn.net/chunlei_zhang/article/details/38778945 这另外一种方法是将solr项目部署到tomcat上,执行to ...

  10. Django写的投票系统2(转)

    在上一篇中 django实例:创建你的第一个应用投票系统(一) 已经介绍基本的功能,并已经启动服务了.这一节介绍数据库相关的东东. 首页打开mysite/settings.py配置文件, 设置数据库打 ...