closures屏幕更新,并打开它,如果它开始?

运行使用Excel的过程时,通常在过程开始时closures一些应用程序设置,然后在过程结束时再次打开它们。

打开和closures应用程序设置的代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace XLTimeTracker { class API { public static void TurnAppSettingsOff() { AddinModule.CurrentInstance.ExcelApp.EnableEvents = false; AddinModule.CurrentInstance.ExcelApp.ScreenUpdating = false; } public static void TurnAppSettingsOn() { if (AddinModule.CurrentInstance.ExcelApp == null) return; AddinModule.CurrentInstance.ExcelApp.EnableEvents = true; AddinModule.CurrentInstance.ExcelApp.ScreenUpdating = true; } } } 

我以下面的方式调用这个程序:

 API.TurnAppSettingsOff(); // my code API.TurnAppSettingsOn(); 

这很好。

但是,说我只想打开运行API.TurnAppSettingsOff()之前的应用程序设置。 什么将是一个很好的方式来编码?

一些想法:

  • 我想我需要以某种方式保存应用程序设置的以前的状态。 例如通过写作:

布尔screenUpdating = AddinModule.CurrentInstance.ExcelApp.ScreenUpdating;

  • 我希望最终的结果是正确的,即使closures和打开appsettings的function也调用另一个closures和打开应用程序设置的function。

  • 我不知道是否最好使用API.TurnAppSettingsOff()这样的命令来设置所有的设置,或者对用户API.TurnScreenUpdatingOff()API.TurnEventsOff()更为明智。

我只是掀起一个内部经理类,处理整个事情类似于以下内容:

 public sealed class ApplicationSettingsManager { readonly object app; readonly Dictionary<string, object> appSettings; public ApplicationSettingsManager(object app) { this.app = app; appSettings = new Dictionary<string, object>(); } public object Application { get { return app; } } public void SaveSetting(string settingName) { var propInfo = app.GetType().GetProperty(settingName); if (propInfo == null) throw new ArgumentException("Specified name is not a valid storable setting.", "setting"); var value = propInfo.GetValue(app); if (appSettings.ContainsKey(settingName)) { appSettings[settingName] = value; } else { appSettings.Add(settingName, value); } } public void SaveAllSettings() { var properties = app.GetType().GetProperties().Where(p => p.CanWrite && p.CanRead && p.SetMethod.IsPublic && p.GetMethod.IsPublic); foreach (var p in properties) { var value = p.GetValue(app); if (appSettings.ContainsKey(p.Name)) { appSettings[p.Name] = value; } else { appSettings.Add(p.Name, value); } } } public void RestoreSetting(string settingName) { if (!appSettings.ContainsKey(settingName)) throw new ArgumentException("Specified name does not correspond to a valid stored setting.", "settingName"); var propInfo = app.GetType().GetProperty(settingName); propInfo.SetValue(app, appSettings[settingName]); } public void RestoreAllSettingas() { foreach (var p in appSettings) { RestoreSetting(p.Key); } } } 

这应该够了吧。 你会使用它如下;

 var excelSettingsManager = new ApplicationSettingsManager(AddinModule.CurrentInstance.ExcelApp); //store all settings you are going to tamper with... excelSettingsManager.SaveSetting("EnableEvents"); excelSettingsManager.SaveSetting("ScreenUpdating"); //change excel setting and do your thing... //... //when done, restore settings excelSettingsManager.RestoreAllSettings(); 

你完成了!

这是我自己的解决scheme,我已经想出来解决这个问题。 这似乎比其他build议的解决scheme更简单。 让我知道如果你认为你有一个更好的解决scheme!

(我的代码恰好在VB.NET中)

处理设置和原始状态存储的类:

 Public Class ApplicationSettings Implements IDisposable Private ScreenUpdating As Boolean Private Events As Boolean Private Production As Boolean = True Public Sub New() MyBase.New() ScreenUpdating = AddinModule.ExcelApp.ScreenUpdating Events = AddinModule.ExcelApp.EnableEvents End Sub Public Sub Dispose() Implements IDisposable.Dispose AddinModule.ExcelApp.ScreenUpdating = ScreenUpdating AddinModule.ExcelApp.EnableEvents = Events End Sub End Class 

这里是我如何在代码中使用它:

 Private Sub AdxRibbonButton1_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton1.OnClick Using New ApplicationSettings 'My code End Using End Sub 

我会build议使用一个整数来表示状态,并使用布尔值来隐藏它。 这就是我的意思:

 this.Working = true; try { // do something } finally { this.Working = false; } 

然后像这样实现Working属性:

 private int working; public bool Working { get { return working > 0; } set { if (value) { working++; } else { working--; } } } 

在内部,它只是记住使用该整数已经设置了多less次。 如果working0 ,那么你就恢复了正常。

您可以根据需要设置Working次数。 只要它> 0 ,它将返回true 。 不要忘记把你的代码包装成一个try...catch否则你将失去计数。

如果将“ Working设置为false则可以执行API调用。 然后将其设置为true

 if (!this.Working) { // do API call this.TurnAppSettingsOff(); } this.Working = true; try { // do something } finally { this.Working = false; } if (!this.Working) { // do reset API call this.TurnAppSettingsOn(); } 

您可以使用Stack<T>类实现后进先出(LIFO)行为。

 struct ExcelEventSettings { public bool EnableEvents; public bool ScreenUpdating; } class Example { private Stack<ExcelEventSettings> settingStack = new Stack<ExcelEventSettings>(); // you can call this function as often as you called SaveAppSettings public void RestoreAppSettings() { if (settingStack.Count == 0) throw new Exception("There is no previous state!"); ExcelEventSettings prevState = settingStack.Pop(); setCurrentEnableEvents(prevState.EnableEvents); setCurrentScreenUpdating(prevState.ScreenUpdating); } public void SetAppSettings(bool enableEvents, bool screenUpdating) { ExcelEventSettings currentState; currentState.EnableEvents = getCurrentEnableEvents(); currentState.ScreenUpdating = getCurrentScreenUpdating(); settingStack.Push(currentState); setCurrentScreenUpdating(enableEvents); setCurrentEnableEvents(screenUpdating); } private bool getCurrentEnableEvents() { // Here you would call your Excel function } private bool getCurrentScreenUpdating() { // Here you would call your Excel function } private void setCurrentEnableEvents(bool value) { // Here you would call your Excel function } private void setCurrentScreenUpdating(bool value) { // Here you would call your Excel function } }