I am already using the Ribbon with XML to add controls to the inspector of a received mail item in Office 2007.
I now want to add a menu/Combo box as well. The problem is that it takes too long to generate the list of items.
Basically is it possible to let the Ribbon be generated and then add the items once they are ready?
I envisage something like:
Create the ribbon with an empty menu
Start a new thread and send it off to get data (thread safe stuff no office)
Get back on the office thread and add the list to the menu
Is it possible to do this?
IMHO, it is difficult to achieve. In Standard ribbon control, values are rather static. They are loaded in to the controls before the ribbon is actually shown. I am not sure if there is a way to intercept it.
It appears it is possible with the use of a DynamicMenu control. Using a numbered list for my answer here is what I did.
Let office show the UI (in this case an Outlook Inspector)
Get the text of the Email Item and then start a new thread to process
When processing is finished get back onto the main UI Thread.
In the Ribbon XML an "empty" DynamicManu exists with a callback for its data
If the result is there is no data then call invalidate and the getVisible call back sets the control to false. Control dissappears.
If there is data to add then invalidate and allow the control to now read the data in the callback.
I would like to thank my secretary for editing my post
Related
I have an VSTO Office/Outlook add-in and ribbon that I want to reload at some point. Unfortunatelly ribbon.invalidate is not something that suits my case, because it just re-fires getLabel etc. methods, while I need to rebuild whole ribbon/group.
I need to force executing method GetCustomUI().
Do you know how can I do it?
There is no way to force Office applications invoke the GetCustomUI callback. If you need to keep your custom ribbon UI hidden at startup by default you can use the getVisible callback for the ribbon controls, including tabs, and when required you may call the IRibbonUI.Invalidate to get your controls callback invoked, so you could return an appropriate value and get your controls appeared on the ribbon.
For example, if an add-in writer implements the getVisible callback procedure for a button, the function is called once, the state loads, and then if the state needs to be updated, the cached state is used instead of recalling the procedure. This process remains in place until the add-in signals that the cached values are invalid by using the Invalidate method, at which time, the callback procedure is again called and the return response is cached. The add-in can then force an immediate update of the UI by calling the Refresh method.
No way to do that - by design, Ribbon is static, even though some controls can be hidden initially and be shown later when their getVisible callback is invoked.
Note that control contents can be populated dynamically (sounds like that is what you actually want), that applies to the dropDown control. In that case, you need to specify getItemCount/getItemLabel/getItemImage/getSelectedItemIndex callbacks.
See the dropDown control description on MSDN: https://learn.microsoft.com/en-us/openspecs/office_standards/ms-customui/700e4451-8706-40c5-8d7b-896e4ae21b69
How can I programmatically restrict the VSTO Add-in Ribbon visibility to a specific AD group only? Can this be controlled directly from the Ribbon XML itself? The plugin is distributed to entire org, but need the ribbon visibility to change by AD group
No, but your own code can easily perform the check and show/hide the ribbon using the getVisible callback specified for your ribbon.
Would be a good idea to perform that check asynchronously and cache the check result before the ribbon is requested by Outlook. If the check completes after the ribbon is returned, call RibbonUI.Invalidate(), which would case Outlook to invoke your getVisible callback again.
we have a working outlook form in our company which includes a button in outlook ribbon
By clicking it a New Mail window opens which has the designed custom form with some combo-boxes, the printscreen image is attached
Below this form there are some VB Macros which fills the combo-boxes and runs some code and when we click Send, a new mail which has this form will be sent for the recipient(s) The Problem is: the recipient receives the vb macros behind this form and sometimes this macros will be accidentally modified and ..., so we don't like this approach
Currently I'm working on a C# VSTO project to replace a AddIn(.dll) with this macro.
My first solution: I have imported a copy of the custom form as a form region and add combo-boxes and other controls in it and fill them and everything was ok, but this form have not been sent by mail to recipient!
My Second solution: I think it would be better to remove all macros from the old custom form and try to fill combo-boxes of the old custom form in my AddIn.
My Question is which solution is better? Is there a better way to do this?
I think I'm going wrong direction because of lack of knowledge with VSTO and outlook forms. please help
Outlook custom forms is an old approach. Defintely, form regions is the better way to go. But it requires better coding skills. Be aware, Outlook form regions can't be sent to recipients with the item.
You need to have the Outlook add-in installed on both sides (sender and recipients) if you want to see the data entered on the form region. Moreover, you have to create corresponding user properties on the item being sent. On the recipient side your add-in can handle the NewMailEx event of the Application class which is fired when a new item is received in the Inbox. So, you may read user properties and display on the form region. Also you may consider using any web server (web service) for uploading such data there. In that case you will be sure the data is preserved when user properties are truncated on the recipient side.
This seems to have been asked several times on here with no real answer:
Accessing Ribbon Controls Programatically in an XML Ribbon
Office Ribbon: How to access a control when the ribbon was created using XML
If a ribbon is created using ribbon xml, as far as I can tell, there is no programmatic exposure of the components defined in that xml. The only obvious limited way to change the state of these components is to use something like an onAction, getContent, getImage event, and the IRibbonControl element offers very little for manipulating the element in question (not to mention, most of those functions only run once, when first rendered).
So I'm trying to find a way to programmatically access those xml ribbon elements.
There is no way to programmatically access Ribbon elements when using Ribbon XML. If you want to change the state of the Ribbon controls - you need to use IRibbonUI.Invalidate() to force a new rendering of the layout (potentially using properties that trigger different behaviors at rendering time via callbacks). This can be a good thing as you have more control over when drawing occurs if you are changing multiple items' state.
See related SO post on updating Ribbon UI control state.
If you want programmatic access to Ribbon elements, you should use the Ribbon Designer. However, as stated on MSDN, the designer doesn't support all customizations. Some speculate that the designer just wraps the Ribbon XML up for you under the hood.
You just have to learn the callback mechanism utilized by the Ribbon XML - there is no control tree for you to gain access to.
How does one set a ribbon button in a Word add-in to be enabled when a document is loaded and disabled when no documents are loaded, just Like most of the built-in buttons?
Can one bind a global flag to the "Enabled" property of the button, or is it more complicated than that? I know I could create a timed loop that checks for changes in Application.Documents, but I'm looking for something "cleaner" if possible.
I've already looked at Disable Own Word 2007 Add-In If No Document Loaded and other related questions.
There are several ways to handle this.
first, you can create a publicly exposed function that returns true or false for the enabled state of your button (however you want to determine that), you then define your ribbon xml to point to that function for the Enabled property getter. If you're dealing with an IExtensibility based addin, then this is the way you'd have to go.
If you're dealing with VSTO, then define your ribbon button in the ribbon designer and make it DISABLED by default.
Then, during the STARTUP event, hook the WORD object, specifically the NEWDOCUMENT, DOCUMENTOPEN and WINDOWACTIVATE events.
In the event handler code for each of those events, enable or disable your buttons as applicable depending on which event fired and which document was activated at the time.
Use the DocumentChange event instead. Hook up will be something like this:
Globals.ThisAddIn.Application.DocumentChange += new EventHandler(OnDocumentChange);
And the Handler
void OnDocumentChange()
{
this.myButton.Enabled = wordApp.Documents.Count > 0;
}
Interesting, my VSTO Contrib project (http://vstocontrib.codeplex.com/documentation) has some features which make ribbon management simpler.
The cleanest way is to use my ribbon factory, but the project will need to be updated to disable buttons if there are no viewmodels to query for the status of the button. In fact it is a scenario I havent really covered.
You have 3 parts an add-in is interested in, the view (window), the context (the document) and the ribbon. VSTO Contrib means you get a view model per context, and it manages/abstracts the ribbon and view so it appears you have a ribbon per context, and it tells you the current active view (for multiple windows showing same document scenarios).
The missing part is if there is a ribbon, but no contexts and no viewmodels, it should invalidate that ribbon control and disable it. It should be a pretty simple change, email me if you are interested in giving VSTO Contrib's RibbonFactory a spin and I can make this change for you.