Simulating a Ribbon Textbox Label

On Wednesday evening I arrived in Stavanger on the coast of Norway, found the sailship

Pantagruel
and met the crew that I will be spending the coming week with.

Thursday we went on a hike rather than sailing, because we happened to be so close to the spectacular


Preikestolen or Pulpit Stone
over
the Lysefjord.
We took our boat over from Stavanger to Jørpeland by motor, since the wind was exactly opposite our direction, and then spent all afternoon hiking through the incredibly beautiful moors and rocks.

On Friday we started the real sailing tour, motoring out of the Stavanger bay in sunshine and very little wind, and catching more wind outside the coast to sail down towards Hidra.
The wind grew and the waves as well, and all of us newbies got a thorough dose of seasickness.
We arrived in a beautiful bay late in the evening and spent most of Saturday recuperating in tranquillity and sunshine.
I also spend a couple of hours trying my hand at sailing a miniature boat, a jolle, before continuing down to Egersund for shopping.

Tonight we are planning to sail further south during the night.
The final goal is to cross over to Denmark and from there cross the Skagerrak to Sweden, then sail on the west coast until we get to Göteborg and head back home.
<!–

I am still underway on my sailing tour along the coast of Norway and western Sweden, if we have not capsized by now…
Here is a little item that I posted before leaving and that I hope you will find as interesting as I did:
–>

We have not yet talked at all about the new ribbon capabilities in the Revit 2011 API.
There are quite a few, as the following excerpt from the What’s New section of the Revit API help file RevitAPI.chm shows:

Additional options for Ribbon customization

There are new Ribbon components supported via the Ribbon API:

  • SplitButton – a pulldown button with a default pushbutton attached
  • RadioGroup – a set of ToggleButtons, where only one of the set can be active at a time
  • ComboBox – a pulldown containing a set of selectable items, which can be grouped optionally
  • TextBox – an input field for users to enter text
  • SlideOut panel – an extra panel can optionally slide down from a Ribbon panel; this panel can contain any of the standard Ribbon components

For ComboBox and TextBox, events are included; these events call your API code when the component is changed by the user.

The new property

  • RibbonItem.Visible

provides control over whether a particular item is visible.

The new properties:

  • RibbonItem.LongDescription
  • RibbonItem.ToolTipImage

allow you to set up an extended tooltip for the Ribbon item. This tooltip can display a longer set of text, and/or a single image.

The new property:

  • PushButton.AvailabilityClassName

allows assignment of an availability class to controlled whether or not the button is available, similar to the option provided for ExternalCommands registered by manifest.

There is also a new option supported for PulldownButton – a separator can now be added between buttons this component.

There is also a new option to add custom panels to the Analyze tab in Revit as well as the Add-Ins tab, via a new overload of Application.CreateRibbonPanel().

As a result of these enhancements, some pre-existing APIs have changed:

  • RibbonPanel.AddButton() has been replaced with RibbonPanel.AddItem()
  • RibbonPanel.AddStackedButtons() overloads have been replaced with RibbonPanel.AddStackedItems() overloads
  • Property RibbonPanel.Items has been replaced with method RibbonPanel.GetItems()
  • Property PulldownButton.Items has been replaced with method PulldownButton.GetItems()
  • Methods RibbonPanel.AddPushButton() and RibbonPanel.AddPulldownButton() have been removed. Use RibbonPanel.AddItem() for this operation.
  • RibbonPanel.AddToPulldown() has been removed. Use PulldownButton.AddItem() for this operation.
  • PulldownButton.AddPushButton() has been removed. Use PulldownButton.AddItem() for this operation.

Some of the new functionality is demonstrated by the Ribbon SDK sample, but not all.

Here is a question on how to simulate a missing widget, a label to describe the use of a text box:

Question: How can I add a label to a ribbon text box like in these two examples from the Revit user interface?

Here is a label for the active workset:

Active workset label

Here is a different label in the Autodesk Seek panel:

Autodesk Seek panel

Could I possible use some stacked items to achieve this?

This is what my attempts so far end up looking like, displaying a textbox lacking a label:

Ribbon textbox lacking label

The code I am using to produce it looks like this:


Sub AddTextBox(ByVal panel As RibbonPanel)
 
  ' fill the text gox information
  Dim txtBoxData As New TextBoxData("TextBox")
 
  txtBoxData.Image = New BitmapImage( _
    New Uri(m_imageFolder + "Basics.ico"))
 
  txtBoxData.Name = "Text Box"
  txtBoxData.ToolTip = "Enter text here"
  txtBoxData.LongDescription _
    = "<p>This is Revit UI Labs.</p><p>Ribbon Lab</p>"
 
  txtBoxData.ToolTipImage = New BitmapImage( _
    New Uri(m_imageFolder + "ImgHelloWorld.png"))
 
  ' create the text box item on the panel 
  Dim txtBox As TextBox = panel.AddItem(txtBoxData)
  txtBox.PromptText = "Enter a comment"
  txtBox.ShowImageAsButton = True
  txtBox.Width = 180
  'txtBox.ItemText = "my text box"
  'txtBox.Name ' this is read only. 
 
  ' p51. we'll talk about events in Lab4
  AddHandler txtBox.EnterPressed, New EventHandler( _
    Of TextBoxEnterPressedEventArgs)( _
    AddressOf txtBox_EnterPressed)
 
End Sub
 
' event hander for the text box above. 
Sub txtBox_EnterPressed( _
  ByVal sender As Object, _
  ByVal e As TextBoxEnterPressedEventArgs)
 
  ' cast sender as TextBox to retrieve text value
  Dim txtBox As TextBox = sender
 
  TaskDialog.Show("TextBox Input", _
    "This is what you typed in: " _
    + txtBox.Value.ToString())
 
End Sub

Answer: The ribbon API does not contain a text label item, so the best alternative might be a disabled pushbutton stacked above the other control.
Here is an example of what this might look like:

Simulate textbox label with disabled pushbutton

Here is the tweaked excerpt from the Ribbon SDK sample that produces this result:


  PushButtonData pushButtonData
    = new PushButtonData(
      "Active Workset",
      "Active Workset",
      AddInPath,
      className );
 
  ComboBoxData comboBoxDataLevel
    = new ComboBoxData( "LevelsSelector" );
 
  IList<RibbonItem> ribbonItemsStacked
    = ribbonSamplePanel.AddStackedItems(
      pushButtonData, comboBoxDataLevel );
 
  ( (PushButton) (ribbonItemsStacked[0]) ).Enabled
    = false;

Many thanks to Mikako Harada and Harry Mattison for this suggestion!


Comments

11 responses to “Simulating a Ribbon Textbox Label”

  1. Zhu XiaoMeng Avatar
    Zhu XiaoMeng

    Hi jeremy:
    Is it possible to import data from excel to schedule view sheet now? And how? I realize that the SDK samples do contains a “PanelSchedule”, but mine is Schedule view.

  2. Zhu XiaoMeng Avatar
    Zhu XiaoMeng

    more precisely, what I want to know is how to get the relation between schedule sheet’s “mark” and the Id in model.

  3. Ruslan Oleinikov Avatar
    Ruslan Oleinikov

    TextBox class looks like limited. I can’t enter special characters like “{}<>
    Is Some way to do this? Main reason it’s enter length in feet… or angle.
    Looks like now only with pop-up window work.

  4. Dear Zhu XiaoMeng,
    Unfortunately, the Revit API does still not provide any access whatsoever to schedules, with the sole exception of electrical panel schedules.
    Access to the latter was added in the Revit 2011 API and is demonstrated by the PanelSchedule SDK sample that you mention:
    http://thebuildingcoder.typepad.com/blog/2010/05/the-revit-mep-2011-api.html
    Other schedules are not accessible programmatically, however.
    Cheers, Jeremy.

  5. Dear Ruslan,
    Just as you say, the ribbon TextBox class currently limits the characters that can be input as you describe. We have an open wish list item to have this restriction removed. The workaround would be as you say, to display your own form and use a standard .NET input control there.
    Cheers, Jeremy.

  6. Jan Dierckx Avatar
    Jan Dierckx

    Hi Jeremy,
    I am a beginner in Revit API and I have a problem with Ribbon TextBoxes. I want the ability to enter a value in a TextBox, placed in a Ribbon I created myself (when the program starts up), and when enter is pressed, this value is written to a ProjectInfo Parameter (which exists, and the entered value is the correct format for the parameter). I use this command to call a function when enter is pressed:
    tBox1.EnterPressed += new EventHandler(ProcessTextToutside);
    and this is the function:
    public void ProcessTextToutside(object sender, Autodesk.Revit.UI.Events.TextBoxEnterPressedEventArgs args)
    {
    // cast sender as TextBox to retrieve text value
    TextBox textBox = sender as TextBox;
    String s = textBox.Value as string;
    Parameter ToutsideP = args.Application.ActiveUIDocument.Document.ProjectInformation.get_Parameter(“test”);
    ToutsideP.Set(double.Parse(s));
    }
    for a very strange reason, the Parameter.Set() doesn’t work in this case, even though the parameter can be called, and it’s not readonly. Do you have any idea how to fix this problem?
    Thanks and kind regards!!
    Jan

  7. Dear Jan,
    The text box in the ribbon is displayed at all times, and thus is comparable to a modeless dialogue.
    If you have followed this blog for a while, you will have noticed that use of the Revit API from a modeless context is a bit special.
    The Revit API can only be used within certain callback contexts, i.e. Revit has to call you to let you know that it is now ok to use the API.
    My initial assumption from your description is that you just need to open a transaction on the document containing the parameter you wish to change.
    Have you tried doing that?
    For instance, something like this:
    public void ProcessTextToutside(
    object sender,
    TextBoxEnterPressedEventArgs args )
    {
    TextBox textBox = sender as TextBox;
    string s = textBox.Value as string;
    Document doc = args.Application.ActiveUIDocument.Document;
    Transaction t = new Transaction( doc );
    t.Start( “Set Parameter” );
    Parameter p = doc.ProjectInformation.get_Parameter( “test” );
    p.Set( double.Parse( s ) );
    t.Commit();
    }
    Cheers, Jeremy.

  8. Aleksey Avatar
    Aleksey

    Hi Jeremy,
    I can create a textbox on Ribbonpanel. How can I get the value from another class, but the same namespace?
    var tab = application.CreateRibbonTab(“tab”);
    RibbonPanel ToolsPanel = application.CreateRibbonPanel(tab, “Instruments”);
    TextBoxData tbData1 = new TextBoxData(“tbName1”);
    TextBox tb1 = ToolsPanel.AddItem(tbData1) as Autodesk.Revit.UI.TextBox;
    tb1.EnterPressed += SetTextBoxValue; //save value
    public void SetTextBoxValue(object sender, TextBoxEnterPressedEventArgs args)
    {
    }

  9. Dear Aleksey,
    Sounds easy to me, and I can think of a number of ways.
    E.g., you could create a public method for setting the value that you call from the other class.
    What problem do you have, please?
    Cheers, Jeremy.

  10. frank halliday Avatar
    frank halliday

    Hi Jeremy,
    I can create a textbox on Ribbonpanel. How can I get the value from another class, but the same namespace?

  11. Dear Frank,
    Simply create a public property or method on the class providing the value, and call that from the method making use of it.
    Cheers, Jeremy.

Leave a Reply to Zhu XiaoMengCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading