一个简单的例子就是大家在使用很多应用程序,例如在使用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. NetBeans工具学习之道:NetBeans的(默认)快捷键

    没什么好介绍的,是netbeans的快捷键,比較全面.看到好多坛子里还在问eclipse下的这个快捷键怎么netbeans下没有呢.曾经收集的,如今列在以下: 事实上,在当前安装的netbeans的 ...

  2. 【剑指offer】二叉树的镜像

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/25915971 题目描写叙述: 输入一个二叉树,输出其镜像. 输入: 输入可能包括多个測试例 ...

  3. 我为什么要创建帮创业者找合伙人的缘创派(ycpai.com)?

    我为什么要创建帮助创业者找合伙人的缘创派(ycpai.com)? 在我发出第一条离开CSDN出来创业的微博后,感谢各位朋友的鼓励.很多朋友问我一些问题,我在这里一并回答,并简单阐述一下我的理念. 问: ...

  4. Eclipse乱码怎么办

    Eclipse里设置编码有三个层次:全局.工程.文件. 文件的编码会覆盖工程的编码,工程的编码会覆盖全局的编码. 我猜测:虽然你的工程编码更改为GBK,但只对新建文件有效. 如果工程中旧有的文件是UT ...

  5. c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)

    一.单元格内容的操作 *****// 取得当前单元格内容 Console.WriteLine(DataGridView1.CurrentCell.Value); // 取得当前单元格的列 Index ...

  6. 自顶向下分析Binder【1】—— Binder实例篇

    欢迎转载,转载请注明:http://blog.csdn.net/zhgxhuaa 一个Binder实例 我们Binder的学习将从以下的一个实例開始.依据Android文档中的描写叙述,创建一个Bin ...

  7. 提领NULL指针

    通常之中导致程序崩溃的最重要的原因是试图取消引用NULL指针.正如在以前的文章中指出,智能指针RefCountPtr和ScopedPtr它提供了一个诊断的执行时间. 但,并不是所有的指针是所有的对象都 ...

  8. poj1797(最短路小变形)

    题目连接:http://poj.org/problem?id=1797 题意: 分析:dp[i]表示到达i点的过程中的最大承受重量,更新到i点时可能有多条路径,由优先队列堆出最大的那条即可. #inc ...

  9. 关于Platinum库的MediaRender具体C++代码实现探讨

    接上篇博文 NDK下 将Platinum SDK 编译成so库 (android - upnp) 讲述了如何利用该代码库编译给android程序调用的so库,其中也提到了,在使用sample-upnp ...

  10. 祖国版Solowheel!IPS103 独轮思维车 - 三个月体验报告

    http://tieba.baidu.com/f?kz=2308652773&mo_device=1