在我使用VSTO創建的C#互操作插件中,我訂閱了Document.BeforeSave事件。但是,另一個MS Word插件在我們的客戶端計算機上也處於活動狀態,該訂閱者也訂閱了完全相同的事件。調用訂單Document.Before保存在C#Word Interop
第三方插件取消默認的Word SaveAsDialog並顯示自己的自定義SaveAsDialog(它是一個DMS對話框)。 我們的用例是我們想要顯示自己的SaveAsDialog並覆蓋第三方的行爲。
Document.BeforeSave事件的調用順序看起來是任意的。有時我們的用戶首先被調用,有時第三方的插件被首先調用。
有沒有辦法可靠取消第三方電話?
編輯:
我曾嘗試以下代碼:
private void ThisAddIn_Startup(object sender, System.EventArgs e) {
Application.DocumentOpen += Application_DocumentOpen;
}
void Application_DocumentOpen(Word.Document Doc) {
Application.DocumentBeforeSave += Application_DocumentBeforeSave;
var handler = new Word.ApplicationEvents2_DocumentBeforeSaveEventHandler(Application_DocumentBeforeSave);
MulticastDelegate multicastDelegate = handler;
var subscribers = handler.GetInvocationList();
for (int i = 0; i < handler.GetInvocationList().Count(); i++) {
Delegate.RemoveAll(multicastDelegate, subscribers[i]);
}
Application.DocumentBeforeSave += Application_DocumentBeforeSave2;
Application.DocumentBeforeSave += Application_DocumentBeforeSave;
}
void Application_DocumentBeforeSave(Word.Document Doc, ref bool SaveAsUI, ref bool Cancel) {
MessageBox.Show("Save 1");
}
void Application_DocumentBeforeSave2(Word.Document Doc, ref bool SaveAsUI, ref bool Cancel) {
MessageBox.Show("Save 2");
}
這不會得到具有2個表示提示消息 「2」,然後 「1」 連續的預期效果。而是顯示「1」,「2」,「1」。
編輯2:此代碼按預期工作:
public class HasEvents {
public delegate void WoeiHandler();
public event WoeiHandler Woei;
public void OnWoei() {
Woei();
}
}
public class Program {
static void Main(string[] args) {
HasEvents hasEvents = new HasEvents();
hasEvents.Woei +=() => Console.WriteLine("ShortVersion");
hasEvents.Woei += Program_Woei;
hasEvents.OnWoei();
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
FieldInfo field = hasEvents.GetType().GetField("Woei", bindingFlags);
MulticastDelegate multicastDelegate = (MulticastDelegate)field.GetValue(hasEvents);
Delegate[] subscribers = multicastDelegate.GetInvocationList();
Delegate current = multicastDelegate;
for (int i = 0; i < subscribers.Length; i++) {
current = Delegate.RemoveAll(current, subscribers[i]);
}
Delegate[] newSubscriptions = new Delegate[subscribers.Length + 1];
newSubscriptions[0] = new HasEvents.WoeiHandler(Program_Woei_First);
Array.Copy(subscribers, 0, newSubscriptions, 1, subscribers.Length);
current = Delegate.Combine(newSubscriptions);
field.SetValue(hasEvents, current);
hasEvents.OnWoei();
}
static void Program_Woei() {
Console.WriteLine("Program_Woei");
}
static void Program_Woei_First() {
Console.WriteLine("First!");
}
}
+1我經歷了衝突VSTO加載項的痛苦。在一個案例http://stackoverflow.com/questions/10528775/how-to-add-a-menu-item-to-excel-2010-cell-context-menu-old-code-doesnt-work另一個加載項正在刪除我的菜單!無論如何,您可以將其他加載項事件處理程序取消訂閱到「Document.BeforeSave」?值得谷歌... – 2014-11-01 07:37:03
'Delegate.RemoveAll(multicastDelegate,訂戶[i]);'允許你重寫(即刪除)來自第三方插件的行爲嗎? – 2014-11-05 22:35:42
我已經使用標準的.NET/C#反射(Delegate.RemoveAll())刪除了第一個事件處理程序。因此,不應該附加和呼叫這個。 – Ruudjah 2014-11-06 08:46:59