我有一个使用VSTO创建的Outlook加载项。该加载项具有Mail.Compose
功能区类型的单个功能区(可视设计器)。功能区选项卡ControlIdType
设置为“自定义”。除了设计器代码之外,加载项中唯一的代码是功能区的以下Load
处理程序。 this.Context.CurrentItem
意外返回null。
private void RibbonComposeMail_Load(object sender, RibbonUIEventArgs e)
{
try
{
var inspector = this.Context as Outlook.Inspector;
if (inspector == null)
{
throw new ApplicationException("Fail - Step 1");
}
var currentMailItem = inspector.CurrentItem as Outlook.MailItem;
if (currentMailItem == null)
{
throw new ApplicationException("Fail - Step 2");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
inspector.CurrentItem
为空。ControlidType
很重要。 “自定义”将导致此问题,但“Office”的默认选项不会出现此问题。Mail.Read
会产生相同的结果,前提是打开的顺序与Inbox>相反。草稿>收件箱(失败)。Marshal.ReleaseComObject
和inspector
对象上currentMailItem
的所有可能调用都没有区别。答案 0 :(得分:3)
我自己也有同样的问题。
我为Outlook日历约会设计了一个功能区栏,我想在每次约会时保存一些额外的字段(例如“此会议是否可以保存旅行?”)
我管理了它,但是,做起来很棘手。
正如您所说,当 Ribbon1_Load 函数启动时, ActiveInspector()为空...那么您应该如何获取有关当前的详细信息电子邮件或日历约会?
这是你需要做的。此示例基于日历约会,但很容易适应EmailItems。
首先,在ThisAddIn.cs文件中,您需要进行一些更改:
public partial class ThisAddIn
{
Outlook.Inspectors inspectors;
public static Outlook.AppointmentItem theCurrentAppointment;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}
当用户打开或创建新的Outlook项目时,我们的“ Inspectors_NewInspector ”功能将被调用,此时,我们 能够获取有关该项的详细信息。项:
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
// This function (apparently) gets kicked off whenever a user opens a new or existing item
// in Outlook (Calendar appointment, Email, etc).
// We can intercept it, modify it's properties, before letting our Ribbon know about it's existance.
//
theCurrentAppointment = null;
object item = Inspector.CurrentItem;
if (item == null)
return;
if (!(item is Outlook.AppointmentItem))
return;
theCurrentAppointment = Inspector.CurrentItem as Outlook.AppointmentItem;
}
使用此代码,我们可以调整 Ribbon1_Load 函数来获取此“theCurrentAppointment”变量,并详细了解用户正在创建/修改的日历约会。
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
// When this function gets called, "Globals.ThisAddIn.Application.ActiveInspector()" is always NULL, so we have
// to fetch the selected AppointmentItem via the ThisAddIn class.
if (ThisAddIn.theCurrentAppointment != null)
{
// Our Ribbon control contains a TextBox called "tbSubject"
tbSubject.Text = ThisAddIn.theCurrentAppointment.Subject
}
}
答案 1 :(得分:3)
RibbonComposeMail_Load
事件被称为一次。但在第3步,它被称为两次。第一次在步骤3调用事件时,this.Context.CurrentItem
为空,但第二次调用该事件时,该属性将保留该电子邮件。
它将NewInspector
事件中的项目值与功能区Load
事件中的项目值进行比较,这让我注意到了这一点。因为步骤3中的事件序列是:Ribbon_Load
,NewInspector
,Ribbon_Load
。我在Ribbon_Load
中收到了MessageBox.Show
到ThisAddIn.CurrentMailItem
邮件主题的主题,但是很惊讶地看到它是上一个电子邮件的主题,即第2步的收件箱电子邮件!
事实证明,如果Ribbon_Load
为空,则解决方案是忽略this.Context.CurrentItem
事件中的所有内容,因为第二个Ribbon_Load
事件即将使用正确的值触发组。至于为什么我们在我的示例的第3步中看到了这种奇怪的行为,而不是第1步?对于实现Outlook对象模型的人来说,这可能是一个问题。
答案 2 :(得分:0)
我不是百分百肯定,但听起来垃圾收集器已经清除了你的内容.Context。
您是否可以尝试将您的Context置于私有字段中并从中获取currentitem:
private readonly Context _context = new Context();
private void RibbonComposeMail_Load(object sender, RibbonUIEventArgs e)
{
try
{
var inspector = _context as Outlook.Inspector;
if (inspector == null)
{
throw new ApplicationException("Fail - Step 1");
}
var currentMailItem = inspector.CurrentItem as Outlook.MailItem;
if (currentMailItem == null)
{
throw new ApplicationException("Fail - Step 2");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
如果这没有帮助,我通常使用Outlook.Application对象来获取currentitem:
readonly Outlook._Application _application = new Outlook.Application();
var selectionList = _application.ActiveExplorer().Selection;
foreach (Object selObject in selectionList)
{
if (selObject is Outlook.MailItem)
{
var outlookMail = (selObject as Outlook.MailItem);
}
}
或者如果您只需要当前项目,就像您的情况一样:
var mailItem = _application.ActiveExplorer().Selection[0];