惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
V
Visual Studio Blog
美团技术团队
L
LINUX DO - 最新话题
Last Week in AI
Last Week in AI
雷峰网
雷峰网
博客园_首页
腾讯CDC
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
J
Java Code Geeks
W
WeLiveSecurity
Apple Machine Learning Research
Apple Machine Learning Research
Spread Privacy
Spread Privacy
博客园 - 聂微东
量子位
Recent Announcements
Recent Announcements
S
Schneier on Security
O
OpenAI News
PCI Perspectives
PCI Perspectives
H
Heimdal Security Blog
T
Tailwind CSS Blog
S
Security Affairs
Y
Y Combinator Blog
P
Privacy International News Feed
Hacker News: Ask HN
Hacker News: Ask HN
Stack Overflow Blog
Stack Overflow Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
U
Unit 42
Webroot Blog
Webroot Blog
Vercel News
Vercel News
Simon Willison's Weblog
Simon Willison's Weblog
B
Blog RSS Feed
S
Secure Thoughts
Microsoft Azure Blog
Microsoft Azure Blog
N
Netflix TechBlog - Medium
V
V2EX
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
DataBreaches.Net
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
L
LangChain Blog
S
Security @ Cisco Blogs
The Hacker News
The Hacker News
The GitHub Blog
The GitHub Blog
C
CERT Recently Published Vulnerability Notes

博客园 - 江南白衣

花开在眼前 多收了三五斗 SQL Server 2008 Spatial Tools Visual Studio 2008 Service Pack 1 Release View to Presenter Communication Polymorphic Databinding Solutions Composite Application Guidance - What is it? AddIn Enabled Applications 带套的日子 NET Debugger Visualizers List Composite Application Guidance for WPF-June 2008 Managed Extensibility Framework (MEF) Managed Extensibility and Add-In Framework 祝我生日快乐 Why use the Entity Framework? Entity Framework FAQ Visual Studio 2008 SP1: Sync Services for ADO.Net with SQL Server 2008 Change Tracking (转) Managed Services for Windows Mobile xUnit.net 1.0.1 Realese
Unsaved Changes When CAB Application Closes: The Notification Pattern
江南白衣 · 2008-08-02 · via 博客园 - 江南白衣

Occasionally this question pops up on the CAB message boards: How do I prevent my application from closing if the user has unsaved changes?

Turns out that there’s a very simple pattern you can utilize to handle this situation. It’s called the Notification Pattern. Jeremy Miller, .Net guru, has a very good blog post on this pattern. He uses it to illustrate a standard way to handle validation on domain objects, but it’s a valuable pattern in other cases too, as I’ll show.

As Martin Fowler writes in his article, the Notification Pattern can be as simple as “a collection of strings which are error messages that the domain generates while it’s doing its work.” This is, in fact, how simple our implementation is where I work. A collection of strings, nothing more. You can use something else besides strings - a rich object with many properties and a public interface - if you like. But for this demonstration I’ll stick to strings.

The easiest way to implement this in CAB is with a Service class. All that is required is an event and a method to call to get notifications. The interface to the service basically looks like this:

public delegate void ApplicationClosingEventHandler(List<string> notifications);
public interface INotificationService
{
event ApplicationClosingEventHandler ApplicationClosing;
List<string> GetNotifications();
}

And the Service itself:


public class NotificationService : INotificationService
{
public virtual event ApplicationClosingEventHandler ApplicationClosing;
public virtual List<string> GetNotifications()
{
List<string> notifications = new List<string>();
if (ApplicationClosing != null)
{
foreach (ApplicationClosingEventHandler handler in ApplicationClosing.GetInvocationList())
{
handler.Invoke(_unsavedChangesNotifications);
}
}
return notifications ;
}
}

WorkItems, Presenters and other classes that know about the dirty state of their models can take a dependency on this Service and subscribe to the ApplicationClosing event. When the event is fired, their handler adds a notification to the list, if it needs to.


public MyPresenter : Presenter<IMyView>
{
private INotificationService _notificationService;
public MyPresenter([ServiceDependency] INotificationService notificationService)
{
_notificationService = notificationService;
_notificationService.ApplicationClosing += new ApplicationClosingEventHandler(AppClosingHandler);
}
private void AppClosingHandler(List<string> notifications)
{
if(myModelIsDirty)
notifications.Add("My object is dirty");
}
}

The next step is to hook the whole thing into the Shell.Closing event. Back in the ShellApplication class, typically in the AfterShellCreated override, you can wire up to the Shell.Closing event:

public override AfterShellCreated()
{
base.AfterShellCreated();
Shell.Closing += new CancelEventHandler(Shell_Closing);
}

In your handler, you can query the INotificationService and get any notifications. If the notification list is empty, you can safely exit the application. Otherwise, pop a MessageBox and alert them.

private void Shell_Closing(object sender, CancelEventArgs ee)
{
INotificationService notificationService = RootWorkItem.Services.Get<INotificationService>();
List<string> notifications = notificationService.GetNotifications();
if(notifications.Count > 0)
{
e.Cancel = true;
// Alert the user
}
}

That’s it. Simple, right? The nice thing about this pattern is that even with simple notifications, like strings, you can still give the user some very useful information on where unsaved changes exist. In our application, for instance, we let the user know which module and “use case” (very broad term here) contains the unsaved changes, so they can find those unsaved changes faster and make the save.

The Notification Pattern is one of the simplest, yet most useful, patterns that you’ll run into in any application, not just CAB. Now go forth and prevent your users from losing data when they close your app!