Adding controls to the ribbon
Adding controls to the ribbon
Can I get an example on adding controls to the ribbon using the manager? And handling the click event. The controls I'm trying to add are not tied to a specific window. They should be available on startup.
Looks like I can still create a CTD to add to the ribbon, but the RegisterHandler method to handle the click event is no longer part of Shell.Package
Looks like I can still create a CTD to add to the ribbon, but the RegisterHandler method to handle the click event is no longer part of Shell.Package
-
- Posts: 411
- Joined: Thu Sep 11, 2008 11:35 am
- Location: Raleigh, NC, USA
- Contact:
Re: Adding controls to the ribbon
You can register a command handler using the new "RegisterHandler" extension method, found in the SoftPro.Select.Controls.Commands namespace. Previous builds would use code like this:
Using Cameron, you'll need to replace the "base" keyword with "this". Also make sure to include the namespace mentioned in order to gain access to the new extension methods.
Code: Select all
base.RegisterHandler(...)
John Morris
Sr. Software Architect
SoftPro
Sr. Software Architect
SoftPro
Re: Adding controls to the ribbon
Thanks. I was missing the SoftPro.Select.Controls.Commands namespace.
Re: Adding controls to the ribbon
Now, I'm trying to hide certain controls based on permission set.
I registered a QueryStatus handler and tried to hide the control in the handler, but it errors out. I know the control exists because I see if I remove the QueryStatus handler.
This is the error log
I registered a QueryStatus handler and tried to hide the control in the handler, but it errors out. I know the control exists because I see if I remove the QueryStatus handler.
Code: Select all
this.RegisterHandler(AdminPackage.NewRibbonTab, null, this.QueryStatusHandler);
...
private void QueryStatusHandler(object sender, QueryStatusEventArgs e)
{
e.Visible = false;
}
Code: Select all
System.NullReferenceException: Object reference not set to an instance of an object.
Stack Trace:
at SoftPro.Select.Controls.RibbonTab.Command_CommandChanged(Object sender, EventArgs e)
at SoftPro.Select.Shell.Commands.Command.OnCommandChanged()
at SoftPro.Select.Managers.CommandManager.UpdateCommandState(QueryStatusEventArgs eventArgs)
at SoftPro.Select.Managers.CommandManager.QueryStatus(QueryStatusEventArgs eventArgs)
at SoftPro.Select.Controls.RibbonTab.QueryStatus(HashSet`1 queried)
at SoftPro.Select.Controls.Ribbon.SoftPro.Select.Shell.ICommandWidget.QueryStatus(HashSet`1 queried)
at SoftPro.Select.Managers.CommandManager.UpdateCommandUI(Boolean force, Boolean delayed)
at SoftPro.Select.Managers.CommandManager.Application_Idle(Object sender, EventArgs e)
at System.EventHandler.Invoke(Object sender, EventArgs e)
at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at SoftPro.Select.Runtime.OnRun()
at SoftPro.Select.Runtime.Start()
at SoftPro.Select.Automation.EnvICE.Start()
XML Log:
<ILExceptionData>
<Point module="Select.exe" classFull="SoftPro.Select.Controls.RibbonTab" methodName="Command_CommandChanged" methodSignature="Void Command_CommandChanged(System.Object, System.EventArgs)" methodToken="0x600072c" ILOffset="28" />
<Point module="SoftPro.Select.Shell.dll" classFull="SoftPro.Select.Shell.Commands.Command" methodName="OnCommandChanged" methodSignature="Void OnCommandChanged()" methodToken="0x600047b" ILOffset="8" />
<Point module="Select.exe" classFull="SoftPro.Select.Managers.CommandManager" methodName="UpdateCommandState" methodSignature="Void UpdateCommandState(SoftPro.Select.Controls.QueryStatusEventArgs)" methodToken="0x600068d" ILOffset="0" />
<Point module="Select.exe" classFull="SoftPro.Select.Managers.CommandManager" methodName="QueryStatus" methodSignature="Boolean QueryStatus(SoftPro.Select.Controls.QueryStatusEventArgs)" methodToken="0x600068b" ILOffset="587" />
<Point module="Select.exe" classFull="SoftPro.Select.Controls.RibbonTab" methodName="QueryStatus" methodSignature="Void QueryStatus(System.Collections.Generic.HashSet`1[System.ComponentModel.Design.CommandID])" methodToken="0x6000734" ILOffset="87" />
<Point module="Select.exe" classFull="SoftPro.Select.Controls.Ribbon" methodName="SoftPro.Select.Shell.ICommandWidget.QueryStatus" methodSignature="Void SoftPro.Select.Shell.ICommandWidget.QueryStatus(System.Collections.Generic.HashSet`1[System.ComponentModel.Design.CommandID])" methodToken="0x60006e0" ILOffset="34" />
<Point module="Select.exe" classFull="SoftPro.Select.Managers.CommandManager" methodName="UpdateCommandUI" methodSignature="Void UpdateCommandUI(Boolean, Boolean)" methodToken="0x6000692" ILOffset="125" />
<Point module="Select.exe" classFull="SoftPro.Select.Managers.CommandManager" methodName="Application_Idle" methodSignature="Void Application_Idle(System.Object, System.EventArgs)" methodToken="0x600066d" ILOffset="8" />
<Point module="CommonLanguageRuntimeLibrary" classFull="System.EventHandler" methodName="Invoke" methodSignature="Void Invoke(System.Object, System.EventArgs)" methodToken="0x6000c3d" ILOffset="-1" />
<Point module="System.Windows.Forms.dll" classFull="System.Windows.Forms.Application+ThreadContext" methodName="System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle" methodSignature="Boolean System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32)" methodToken="0x6001344" ILOffset="8" />
<Point module="System.Windows.Forms.dll" classFull="System.Windows.Forms.Application+ComponentManager" methodName="System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop" methodSignature="Boolean System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32)" methodToken="0x6001308" ILOffset="476" />
<Point module="System.Windows.Forms.dll" classFull="System.Windows.Forms.Application+ThreadContext" methodName="RunMessageLoopInner" methodSignature="Void RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)" methodToken="0x6001337" ILOffset="478" />
<Point module="System.Windows.Forms.dll" classFull="System.Windows.Forms.Application+ThreadContext" methodName="RunMessageLoop" methodSignature="Void RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)" methodToken="0x6001336" ILOffset="19" />
<Point module="Select.exe" classFull="SoftPro.Select.Runtime" methodName="OnRun" methodSignature="Void OnRun()" methodToken="0x60008d6" ILOffset="59" />
<Point module="Select.exe" classFull="SoftPro.Select.Runtime" methodName="Start" methodSignature="Void Start()" methodToken="0x60008d2" ILOffset="75" />
<Point module="Select.exe" classFull="SoftPro.Select.Automation.EnvICE" methodName="Start" methodSignature="Void Start()" methodToken="0x600048e" ILOffset="197" />
</ILExceptionData>
Call Stack:
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at System.Diagnostics.TraceEventCache.get_Callstack()
at SoftPro.Select.LogTraceListener.OnLog(TraceEventCache eventCache, String message, TraceEventType eventType)
at SoftPro.Select.LogTraceListener.TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, String message)
at System.Diagnostics.TraceInternal.TraceEvent(TraceEventType eventType, Int32 id, String format, Object[] args)
at System.Diagnostics.Trace.TraceError(String message)
at SoftPro.Select.Automation.EnvICE.Start()
at System.Runtime.Remoting.Messaging.Message.Dispatch(Object target, Boolean fExecuteInContext)
at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)
at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)
at System.Runtime.Remoting.Messaging.ServerObjectTerminatorSink.SyncProcessMessage(IMessage reqMsg)
at SoftPro.Select.Shell.SynchronizationContextAspect.SyncProcessMessage(IMessage msg)
at System.Runtime.Remoting.Lifetime.LeaseSink.SyncProcessMessage(IMessage msg)
at System.Runtime.Remoting.Messaging.ServerContextTerminatorSink.SyncProcessMessage(IMessage reqMsg)
at System.Runtime.Remoting.Channels.CrossContextChannel.SyncProcessMessageCallback(Object[] args)
at System.Threading.Thread.CompleteCrossContextCallback(InternalCrossContextDelegate ftnToCall, Object[] args)
at System.Threading.Thread.InternalCrossContextCallback(Context ctx, IntPtr ctxID, Int32 appDomainID, InternalCrossContextDelegate ftnToCall, Object[] args)
at System.Runtime.Remoting.Channels.CrossContextChannel.SyncProcessMessage(IMessage reqMsg)
at System.Runtime.Remoting.Proxies.RemotingProxy.CallProcessMessage(IMessageSink ms, IMessage reqMsg, ArrayWithSize proxySinks, Thread currentThread, Context currentContext, Boolean bSkippingContextChain)
at System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg, Boolean useDispatchMessage, Int32 callType)
at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(IMessage reqMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at SoftPro.Select.Automation.EnvICE.Start()
at SoftPro.Select.Automation.EnvICE.Run(String rootSuffix, Boolean noSplash, Boolean setupMode, Boolean log, Boolean embedding, Dictionary`2 args, String freeArg)
at SoftPro.Select.Program.Main(String[] args)
-
- Posts: 411
- Joined: Thu Sep 11, 2008 11:35 am
- Location: Raleigh, NC, USA
- Contact:
Re: Adding controls to the ribbon
Ribbon tabs do not support the QueryStatus routine in the normal fashion. It is against ribbon usage guidelines to hide a tab once the application is up and running, unless that tab is a contextual tab. (See Microsoft's Ribbon Guidelines for more details.)
Once you hide a ribbon tab using a QueryStatus call like this, you have to Unregister the handler, or else it will create issues.
Try this:
Once you hide a ribbon tab using a QueryStatus call like this, you have to Unregister the handler, or else it will create issues.
Try this:
Code: Select all
private void QueryStatusHandler(object sender, QueryStatusEventArgs e)
{
e.Visible = false;
this.UnregisterHandler(RibbonTabID, null, this.QueryStatusHandler);
}
John Morris
Sr. Software Architect
SoftPro
Sr. Software Architect
SoftPro
Re: Adding controls to the ribbon
I understand that it does not meet the ribbon usage guidelines, but is there another way to add a non-contextual ribbon tab without defining them in CTD file? I had asked this in my original post. Or perhaps there is a way to define them in the CTD, but not create them on start up and allow it to be added later???
In the QueryStatus handler, I am unregistering the handler but did not add that in my example. The exception, however, is thrown on "e.Visible = false;" on it's first occurrence. In Boylan, the sender was actually the Command object, so we did the following.
In the QueryStatus handler, I am unregistering the handler but did not add that in my example. The exception, however, is thrown on "e.Visible = false;" on it's first occurrence. In Boylan, the sender was actually the Command object, so we did the following.
Code: Select all
private void QueryStatusHandler(object sender, QueryStatusEventArgs e)
{
Command cmd = (Command)sender;
cmd.Visible = false;
this.UnregisterHandler(RibbonTabID, null, this.QueryStatusHandler);
}
-
- Posts: 411
- Joined: Thu Sep 11, 2008 11:35 am
- Location: Raleigh, NC, USA
- Contact:
Re: Adding controls to the ribbon
RibbonTabs must be defined in a CTD.
Ah, I see the issue with your code snippet now. Instead of using the sender argument, use the EventArgs argument. This was one of the breaking changes in the shell. Sorry for the confusion.
Ah, I see the issue with your code snippet now. Instead of using the sender argument, use the EventArgs argument. This was one of the breaking changes in the shell. Sorry for the confusion.
John Morris
Sr. Software Architect
SoftPro
Sr. Software Architect
SoftPro
Re: Adding controls to the ribbon
John, in Cameron, I am using the visible property on the QueryStatusEventArgs argument, which is throwing an error. The previous post (using the sender argument) was the code we currently use in Boylan.
-
- Posts: 411
- Joined: Thu Sep 11, 2008 11:35 am
- Location: Raleigh, NC, USA
- Contact:
Re: Adding controls to the ribbon
OK.
I'm not seeing that behavior on my latest builds. Let me look into getting an updated build to you and see if the issue is already resolved.
I'm not seeing that behavior on my latest builds. Let me look into getting an updated build to you and see if the issue is already resolved.
John Morris
Sr. Software Architect
SoftPro
Sr. Software Architect
SoftPro