Skip to content

ProGuide Combo boxes

UmaHarano edited this page Nov 6, 2023 · 20 revisions
Language:      C#
Subject:       Framework
Contributor:   ArcGIS Pro SDK Team <arcgisprosdk@esri.com>
Organization:  Esri, http://www.esri.com
Date:          10/02/2023
ArcGIS Pro:    3.2
Visual Studio: 2022

This ProGuide explains the step by step process on how to declare a combo box. However this is for reference only. The recommended approach is to run the combo box item template.

In this topic

How to declare a Combo box

Combo box controls are similar to Edit box controls, but also provide a drop-down list. They are declared in DAML using the comboBox element within the controls container.

A Combo box is declared using the id, className, and sizeString attributes. It can be configured to appear with or without a caption. Use the readOnly attribute to set the Combo box to read-only. Use the condition attribute to assign a predefined condition to control the enabled state.

The sizeString attribute is used to establish the width of the control. This string is representative of the kind of input that appears in the control. The sizeString attribute can also be updated at runtime.

Use the ItemHeight and ItemWidth attributes to customize the width and height of the control on the ribbon. Use the rows attribute to set the number of rows that display on the drop-down list.

The Combo box is referenced on a group using the comboBox control with the refID attribute.

<groups>
   <group>
      <labelControl refID="esri_mapping_labelClassFieldLabel" size="small"/>
      <comboBox refID="esri_mapping_labelClassExpressionComboBox" size="small" />
      <button refID="esri_mapping_labelClassExpressionButton" size="small" />
   </group>
</groups>

<controls>  
   <comboBox id="esri_mapping_labelClassExpressionComboBox" 
             condition="esri_mapping_singleFeatureLayerSelectedCondition" caption=""             
             className="Labeling.Ribbon.LabelClassExpressionComboBox" isEditable="false" isReadOnly="true" 
             itemWidth="140">
          <tooltip heading="Label Class">Set the label expression for the current label class.
               <disabledText></disabledText></tooltip>
   </comboBox>
</controls>  

The className attribute references the Combo box implementation. This is a class that inherits from the ArcGIS.Desktop.Framework.Contracts.ComboBox base class. Combo boxes populate dynamically at runtime by this derived class. The list consists of ComboBoxItem objects, each with a caption, optional image, and generic tag.

internal class LabelClassExpressionComboBox : ArcGIS.Desktop.Framework.Contracts.ComboBox
{
   public LabelClassExpressionComboBox ()
   {
      // TODO : add code here to dynamically populate the combobox
   }
}

Populating a Combo box

Combo boxes populate dynamically at runtime by their derived class. The Combo box list consists of ComboBoxItem objects, each with a caption, optional image, and generic tag.

internal class MyComboBox : ArcGIS.Desktop.Framework.Contracts.ComboBox
{
   public MyComboBox()
   {
      this.Add(new ComboBoxItem("Item1"));
      this.Add(new ComboBoxItem("Item2"));
      this.Add(new ComboBoxItem("Item3"));
      this.Add(new ComboBoxItem("Item4"));
      this.Add(new ComboBoxItem("Item5"));
   }
}

Determine when a selection occurs

The base ArcGIS.Desktop.Framework.Contracts.ComboBox class provides an OnSelectionChange method that can be overridden by your implemented class to provide a custom action when the user selects an item from the Combo box. See the code snippet below for how this looks.

internal class MyComboBox : ArcGIS.Desktop.Framework.Contracts.ComboBox
{
   public MyComboBox()
   {
      this.Add(new ComboBoxItem("Item1"));
      this.Add(new ComboBoxItem("Item2"));
      this.Add(new ComboBoxItem("Item3"));
      this.Add(new ComboBoxItem("Item4"));
      this.Add(new ComboBoxItem("Item5"));
   }

   protected override void OnSelectionChange(ComboBoxItem item)
   {
      // TODO - add specific custom code here
   }
}

Customizing Content with a Data Template File

There may be situations where the combobox content needs to be styled beyond what the out-of-the-box ComboBoxItem class can provide. In this case you will need to provide a dataTemplateFile containing the xaml styling for your combo box items. This is a similar pattern to the use of a data template file for customizing gallery content items.

To use a data template file with a combo box, first create a WPF resource dictionary and add it to the add-in Visual Studio project. Within the resource dictionary, create a WPF DataTemplate defining the desired item styling. There are no restrictions to the WPF styling though keep in mind that the items should be styled to fit within the combo box edit box and drop down. In this example, custom styling is being applied to show a custom "ColorItem" class which will be used to make a color picker combo on the ribbon:

<ResourceDictionary ...>

  <DataTemplate x:Key="PickAColorCombo">
    <DockPanel >
     <TextBlock Width="60" Text="{Binding Name}" DockPanel.Dock="Left"
       VerticalAlignment="Center"/>
     <Border BorderBrush="{DynamicResource Esri_Black}"
	BorderThickness="1"
	CornerRadius="2"
	Margin="0,1,0,1"
	Background="{Binding Brush}"
	Width="40"
	Height="20"
	DockPanel.Dock="Right">
     </Border>
    </DockPanel>
  </DataTemplate>
</ResourceDictionary>

Each item in the combo will have a color swatch (on the right) along with the name of the/its color (on the left).

In the Config.daml, the <comboBox ...> daml entry is modified with a templateID and dataTemplateFile attribute. The WPF DataTemplate x:Key is used as the comboBox templateID and the dataTemplateFile contains the pack uri of the resource dictionary containng the custom item styling:

 <controls>
   <!-- add your controls here -->
   <comboBox id="Acme_ChangeSymbolColor_PickAColor" caption="Pick a color" 
       className="PickAColorCombo" itemWidth="110" extendedCaption="Pick a color" 
       dataTemplateFile="pack://application:,,,/AcmeAddin;component/CustomComboResources.xaml" 
       templateID="PickAColorCombo" isEditable="false" isReadOnly="true" resizable="true">
          <tooltip heading="Tooltip Heading">Pick a color from the list of colors<disabledText /></tooltip>
   </comboBox>

On initialization, the combo box should populate its list with the relevant items (in this case the custom ColorItem instances) same as when using the out-of-the-box ComboBoxItem:

//custom color item shown in the combo
internal class ColorItem {
    private Color _color = System.Windows.Media.Colors.Black;
    private SolidColorBrush _brush = null;
    private string _name = "";

    public ColorItem(Color color) {
      Initialize(color);
    }

    private void Initialize(Color color) {
      _color = color;
      _name = NameFromColor(_color);
      _brush = new SolidColorBrush(_color);
    }

    #region Properties

    public string Name => _name;

    public SolidColorBrush Brush => _brush;

    public Color Color => _color;

    #endregion

    internal string NameFromColor(Color col) {
      PropertyInfo colorProperty = typeof(System.Windows.Media.Colors).GetProperties()
        .FirstOrDefault(p => Color.AreClose((Color)p.GetValue(null), col));
      return colorProperty != null ? colorProperty.Name : "";
    }
  }

//initialize the list of available colors for the picker (in the module in this case)...
internal class Module1 : Module {
  private List<ColorItem> _colorList = new List<ColorItem>();
  private ColorItem _colorItem = null;
  ...

  protected override bool Initialize() {
	_colorList = new List<ColorItem>();
	_colorList.Add(new ColorItem(Colors.Red));
	_colorList.Add(new ColorItem(Colors.Green));
	_colorList.Add(new ColorItem(Colors.Blue));
	_colorList.Add(new ColorItem(Colors.Orange));
	_colorList.Add(new ColorItem(Colors.Yellow));
	_colorList.Add(new ColorItem(Colors.Purple));
	return true;
  }

  public List<ColorItem> ColorList => _colorList;

  public ColorItem SelectedColorItem {
   get {
     return _colorItem;
   }
   set {
     _colorItem = value;
   }
 }
 ...

//populate the combo box with the custom color items
//and handle the combo box item selection
internal class PickAColorCombo : ComboBox {
  private bool _isInitialized;

  public PickAColorCombo() {
    UpdateCombo();
  }

  private void UpdateCombo() {
    //populate the combobox with your desired items  
    if (_isInitialized)
      SelectedItem = ItemCollection.FirstOrDefault();

    if (!_isInitialized) {
      Clear();

     //Add the custom color items to the combobox
     foreach(var colorItem in Module1.Current.ColorList) {
       Add(colorItem);
     }
     _isInitialized = true;
    }

    Enabled = true; //enables the ComboBox
    SelectedItem = ItemCollection.FirstOrDefault();
  }

  protected override void OnSelectionChange(object item) {
    if (item == null) return;

    //handle the color item selection
    Module1.Current.SelectedColorItem = (ColorItem)item;
  }
}

The final product:

Color Picker Combo

Developing with ArcGIS Pro

    Migration


Framework

    Add-ins

    Configurations

    Customization

    Styling


Arcade


Content


CoreHost


DataReviewer


Editing


Geodatabase

    3D Analyst Data

    Plugin Datasources

    Topology

    Object Model Diagram


Geometry

    Relational Operations


Geoprocessing


Knowledge Graph


Layouts

    Reports


Map Authoring

    3D Analyst

    CIM

    Graphics

    Scene

    Stream

    Voxel


Map Exploration

    Map Tools


Networks

    Network Diagrams


Parcel Fabric


Raster


Sharing


Tasks


Workflow Manager Classic


Workflow Manager


Reference

Clone this wiki locally