NetOffice - Custom Task Pane in a Appointment window in Outlook - vsto

I found out that it's possible to add custom task panes to individual windows like e.g. the appointment with this code snippet:
public void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Microsoft.Office.Tools.CustomTaskPane myCustomTaskPane;
if(Inspector.CurrentItem is Microsoft.Office.Interop.Outlook.AppointmentItem ) {
UserControl uc1 = MyUserControl();
myCustomTaskPane = getAddIn().CustomTaskPanes.Add(uc1, "MyPanel",Inspector);
myCustomTaskPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight;
myCustomTaskPane.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
myCustomTaskPane.Visible = true;
}
//Additionally You can add a property change listener to the current Item here
}
however, I use 'NetOffice' instead of VSTO to have the add-in compatible with various Outlook versions. And there the add-in doesn't have the CustomTaskPanes property, and the TaskPanes.Add property isn't overloaded to allow adding custom panes on other window than the main explorer.

Ok, worked it out in following way.
In the ComAddin class I have a local variable
Office._CustomTaskPane _taskPane;
and I set the variable on the overriden CTPFactoryAvailable method:
public override void CTPFactoryAvailable(object CTPFactoryInst)
{
_ctpFactory = new NetOffice.OfficeApi.ICTPFactory(this.Application, CTPFactoryInst);
}
Then - when the addin is loaded - I'm adding an event handler to the NewInspectorEvent event:
private void Addin_OnStartupComplete(ref Array custom)
{
var inspectors = Application.Inspectors as NetOffice.OutlookApi.Inspectors;
inspectors.NewInspectorEvent += Inspectors_NewInspectorEvent;
}
In the event handler for creating a new inspector window, I'm creating the pane:
private void Inspectors_NewInspectorEvent(_Inspector Inspector)
{
var ai = Inspector.CurrentItem as AppointmentItem;
if (ai == null)
return;
var ins = Inspector as NetOffice.OutlookApi.Inspector;
_taskPane = _ctpFactory.CreateCTP(typeof(Addin).Assembly.GetName().Name + ".UserControl1", "My title", Inspector);
_taskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionTop;
_taskPane.Height = 50;
_taskPane.Visible = true;
}
This draft proof of concept works for me.

Related

XAML forms have second picker sorted based on selection in first picker

I have 2 dropdowns (pickers) on a XAML form. The first is an ObservabelCollection of Territories. The second is an ObservableCollection of type Tracks. When the form loads my ViewModel loads both collections and each collection is bound to a picker. I want to filter and display only those tracks that are associated with the selected territory in the second picker.
FYI-the second picker is disabled until a selection is made in the first. Actually I don't require that the second picker's data source be set as the form loads, unless the solution requires it. The selection in the first picker will be the key to filter the data for the second.
I have tried to handle the filtering in the Territory picker's SelectedIndexChanged event but my ObservableCollection 'tracks' is not exposed here.
private void territoryPicker_SelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
string territory = picker.SelectedItem.ToString();
Tracks _track = tracks.Where(X => X.Territory = territory);<<<==== Does not work
trackPicker.ItemsSource = _track.Track;<<<==== Does not work
trackPicker.IsEnabled = true;
}
I've also tried to not build the Tracks OC until after the Territory is selected like this:
private void territoryPicker_SelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
string territory = picker.SelectedItem.ToString();
TrackViewModel vm = new TrackViewModel();
var _tracks = (Tracks)vm.Tracks; <<<<<==== This does not work
trackPicker.IsEnabled = true;
}
The ViewModel runs and the tracks are loaded via the API but when it returns here Tracks is empty.
I'm open to a reasonable solution (not 3rd party controls/packages) that will accomplish this task . Thanks
I figured it out by stumbling over the answer while researching another issue. I have been referencing my viewmodel in the {content].xaml page like this.
<ContentPage.BindingContext>
<vm:TrackViewModel />
</ContentPage.BindingContext>
When doing so the resources of that vm were not available in the code behind. But when I reference the VM in the page constructor Like this:
public partial class RequestmyTracks : ContentPage
{
TrackViewModel trackviewmodel = new TrackViewModel();
And then bind it here:
public RequestmyTracks()
{
InitializeComponent();
BindingContext = trackviewmodel;
}
The trackviewmodel is accessible in the SelectedIndexChanged event and everything else was really straight forward, Which looks like this:
private void territoryPicker_SelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
string territory = picker.SelectedItem.ToString();
ObservableCollection<Tracks> dah = (ObservableCollection<Tracks>)trackviewmodel.Tracks;
List<string> trackNames = new List<string>();
foreach (var track in dah)
{
if (track.Territory == territory)
trackNames.Add(track.Track);
}
trackPicker.ItemsSource = trackNames;
if(trackNames.Count ==1)
trackPicker.SelectedIndex = 0;
trackPicker.IsEnabled = true;
}
Thanks for the help

Outlook Addin: Custom Ribbon not visible in the main application window although RibbonType includes to Microsoft.Outlook.Explorer

I created an Outlook 2016 Addin which shows perfectly in the Inspector Windows for Appointments using the Ribbon Designer.
According to the documentation, I added the RibbonType Microsoft.Outlook.Explorer.
I would have expected that it would also show up on the start screen of Outlook:
Also, I cannot find any suitable RibbonType to set additionally so that the Addin shows on the start screen. Which should I add?
Where can I find good additional documentation of how to customize Outlook's Ribbons?
Do I have to switch to XML Customization? Is there documentation for how to move from Designer to XML?
I also included the Designer Code:
namespace OutlookAddIn4
{
partial class MyAddIn : Microsoft.Office.Tools.Ribbon.RibbonBase
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
public MyAddIn()
: base(Globals.Factory.GetRibbonFactory())
{
InitializeComponent();
}
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">"true", wenn verwaltete Ressourcen gelöscht werden sollen, andernfalls "false".</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Komponenten-Designer generierter Code
/// <summary>
/// Erforderliche Methode für Designerunterstützung -
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.tab1 = this.Factory.CreateRibbonTab();
this.group1 = this.Factory.CreateRibbonGroup();
this.btnAddMyAddIn = this.Factory.CreateRibbonButton();
this.btnViewInMyAddIn = this.Factory.CreateRibbonButton();
this.btnRemoveFromMyAddIn = this.Factory.CreateRibbonButton();
this.btnSettings = this.Factory.CreateRibbonButton();
this.tab1.SuspendLayout();
this.group1.SuspendLayout();
this.SuspendLayout();
//
// tab1
//
this.tab1.ControlId.ControlIdType = Microsoft.Office.Tools.Ribbon.RibbonControlIdType.Office;
this.tab1.ControlId.OfficeId = "TabAppointment";
this.tab1.Groups.Add(this.group1);
this.tab1.Label = "TabAppointment";
this.tab1.Name = "tab1";
//
// group1
//
this.group1.Items.Add(this.btnAddMyAddIn);
this.group1.Items.Add(this.btnViewInMyAddIn);
this.group1.Items.Add(this.btnRemoveFromMyAddIn);
this.group1.Items.Add(this.btnSettings);
this.group1.Label = "MyAddIn";
this.group1.Name = "group1";
this.group1.Position = this.Factory.RibbonPosition.AfterOfficeId("GroupActions");
//
// btnAddMyAddIn
//
this.btnAddMyAddIn.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.btnAddMyAddIn.Image = global::OutlookAddIn4.Properties.Resources.do_48x48;
this.btnAddMyAddIn.Label = "Add Minutes";
this.btnAddMyAddIn.Name = "btnAddMyAddIn";
this.btnAddMyAddIn.ShowImage = true;
this.btnAddMyAddIn.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnAddMyAddIn_Click);
//
// btnViewInMyAddIn
//
this.btnViewInMyAddIn.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.btnViewInMyAddIn.Image = global::OutlookAddIn4.Properties.Resources.do_48x48;
this.btnViewInMyAddIn.Label = "View Minutes";
this.btnViewInMyAddIn.Name = "btnViewInMyAddIn";
this.btnViewInMyAddIn.ShowImage = true;
this.btnViewInMyAddIn.Visible = false;
this.btnViewInMyAddIn.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.ViewInMyAddIn_Click);
//
// btnRemoveFromMyAddIn
//
this.btnRemoveFromMyAddIn.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.btnRemoveFromMyAddIn.Image = global::OutlookAddIn4.Properties.Resources.do_48x48;
this.btnRemoveFromMyAddIn.Label = "Remove Minutes";
this.btnRemoveFromMyAddIn.Name = "btnRemoveFromMyAddIn";
this.btnRemoveFromMyAddIn.ShowImage = true;
this.btnRemoveFromMyAddIn.Visible = false;
this.btnRemoveFromMyAddIn.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.RemoveFromMyAddIn_Click);
//
// btnSettings
//
this.btnSettings.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.btnSettings.Image = global::OutlookAddIn4.Properties.Resources.do_48x48;
this.btnSettings.Label = "Settings";
this.btnSettings.Name = "btnSettings";
this.btnSettings.ShowImage = true;
this.btnSettings.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.Settings_Click);
//
// MyAddIn
//
this.Name = "MyAddIn";
this.RibbonType = "Microsoft.Outlook.Appointment, Microsoft.Outlook.Explorer";
this.StartFromScratch = true;
this.Tabs.Add(this.tab1);
this.Load += new Microsoft.Office.Tools.Ribbon.RibbonUIEventHandler(this.MyAddIn_Load);
this.tab1.ResumeLayout(false);
this.tab1.PerformLayout();
this.group1.ResumeLayout(false);
this.group1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
internal Microsoft.Office.Tools.Ribbon.RibbonTab tab1;
internal Microsoft.Office.Tools.Ribbon.RibbonGroup group1;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnAddMyAddIn;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnViewInMyAddIn;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnRemoveFromMyAddIn;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnSettings;
internal SettingsForm settingsForm;
}
partial class ThisRibbonCollection
{
internal MyAddIn MyAddIn
{
get { return this.GetRibbon<MyAddIn>(); }
}
}
}
I was kind of stupid.
The RibbonType is only a rough preselection of the areas where your addin is enabled to be visible. To precisely define the areas where to add your Ribbon you also need to define
your tab's OfficeId as follows:
this.tab1.ControlId.OfficeId = "TabAppointment";
From the example code above you see this is set to TabAppointment.
to find other valid tabs you may find the following list helpful
From this I conclude: If you want to show your Custom Ribbon in multiple windows (e.g. main window and calendar and appointment) you want to have multiple ribbons attached to various OfficeIds.
The Ribbon (Visual Designer) item does not support all possible types of Ribbon customization. To customize the ribbon in advanced ways, you can export the ribbon from the designer to Ribbon XML and edit the XML directly. The How to: Export a ribbon from the Ribbon Designer to Ribbon XML article describes the task in detail, so you may continue with XML and all features provided by the Fluent UI.
The Fluent UI (aka Ribbon UI) is described in-depth in the following series of articles:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

How detect when user choose NEW or OPEN mail in Outlook VSTO

I'm programming a VSTO in Outlook 2016 and I would like to enable/disable buttons in a Ribbon, based on the user's action of START A NEW MESSAGE or just OPEN/READ a message.
My problem is HOW detect when the user pressed NEW MAIL or just open a sent/received one message.
Could anyone help me?
Thanks!
This tutorial actually deals with this exact scenario:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector +=
new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}
Specifically, you attach to this.Appliaction.Inspectors. The tutorial takes the opportunity to modify the Subject and Body properties of the new MailItem:
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Outlook.MailItem mailItem = Inspector.CurrentItem as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID == null)
{
mailItem.Subject = "This text was added by using code";
mailItem.Body = "This text was added by using code";
}
}
}

Disable send update to all attendees VSTO

I'm using VSTO to develop add-in for Outlook.
When using Send method of MeetingItem (AppointmentItem), how can I disable Send Update to All Attendees popup? It always show when I call Send of existing meeting.
I only found ForceUpdateToAllAttendees property but it make the update send to all attendees, that would be wrong if user don't want to send updates to all attendees.
EDIT:
This is my code
void Application_ItemSend(object item, ref bool Cancel)
{
var form = new SC01(item);
form.Show();
Cancel = true; // prevent mail sending
}
...
in SC01 form:
private void btn_OK_Click(object sender, EventArgs e)
{
var meetingItem = _item As MeetingItem; // _item is private field of SC01
meetingItem.GetAssociatedAppointment(false).Send(); // this Send() will make sending option (to update attendees only or to all attendees
}
sorry I was away some days. I think I have the solution, althuogh I only "speak" vba - but in the end it is all the same...
leave away the line:
Cancel = true; // prevent mail sending
and also the line:
meetingItem.GetAssociatedAppointment(false).Send();
as far as I know the item will not be sent anyway as long as the form is not hidden again.
I hope this works!
Max
just had another idea that should solve your Problem:
void Application_ItemSend(object item, ref bool Cancel)
{
var form = new SC01(item);
form.Show();
'''next line is new and prevents the first popup
item.ForceUpdateToAllAttendees = TRUE
Cancel = true; // prevent mail sending
}
... in SC01 form:
private void btn_OK_Click(object sender, EventArgs e)
{
var meetingItem = _item As MeetingItem; // _item is private field of SC01
'''next line is new => popup Comes now
meetingItem.ForceUpdateToAllAttendees = FALSE
meetingItem.GetAssociatedAppointment(false).Send(); // this Send() will make sending option (to update attendees only or to all attendees
}

SharePoint 2010 event receiver,List Item Events, Document library,event ItemAdded not firing

in SharePoint Server 2010 i have a document library and i want to create sub-folders every time a folder created, i have a code snippet but it's not working, i tried to debug but also the event isn't firing, could any one help me please and here is my code:
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item was added.
/// </summary>
private string[] subFolders = new string[] { "sub-folder1", "sub-folder2", "sub folder3" };
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
SPWeb web = properties.OpenWeb();
SPDocumentLibrary ProductsLibrary = (SPDocumentLibrary)web.Lists[properties.ListId];
if (properties.ListItem.ContentType.Name.ToLower() == "new content type" && properties.ListItem.Folder.ParentFolder.ToString() == ProductsLibrary.RootFolder.ToString())
{
string Url = properties.ListItem.ParentList.RootFolder.ServerRelativeUrl.ToString();
SPFolder libFolder = ProductsLibrary.RootFolder.SubFolders[properties.ListItem.Name];
string newFolderUrl = (web.Url + "/" + libFolder.ToString());
foreach (string subfolder in subFolders)
{
SPListItem newSubFolder = ProductsLibrary.Items.Add(newFolderUrl, SPFileSystemObjectType.Folder, subfolder);
newSubFolder.Update();
}
}
}
}
thank you
the solution is to opent the elements.xml and replace the
with the and the code will run perfectly.
Make sure
you have added this event receiver as part of a feature
the feature containing this event receiver is activated
Event wont fire, if you have not followed the above steps