Using the Refresh Attributes Event

Introduction

When you develop a component, it may be designed such that its attributes are dependent on each other. In other words, a change to the value of one attribute can cause the value of one or more attributes to change as well. For example, the list box control has several attributes that are dependent on each other, two of which are selectedIndex and selectedItem. When a user sets the value for either attribute using the Properties window, the value of the other attribute is updated to keep them synchronized. The behavior that updates other attributes is typically implemented in the attribute's setCAM.
Consider what happens when a user sets the value of selectedIndex to 5. The setCAM for the selectedIndex attribute executes and sets the new value for the selectedItem attribute. If a user were to update selectedItem, its setCAM would update selectedIndex.
If any of these attributes are changed at build time while the Properties window is open, the “refresh Attributes” event can be sent to notify the Properties window that it should refresh its display to reflect the new attribute values. The Properties window is designed to listen for the “refresh Attributes” event.
It is the responsibility of the component developer to send the event. Typically, you can send this event in the setCAM following any code that changes the other attribute values. For example:
if frameID.buildTime='Yes' then
   _sendEvent('refresh Attributes', attributeList);
where attributeList is a list that contains information that the Properties window uses to update its displayed attribute values. For performance reasons, the event should be sent only if the frame is displayed at build time. There is no reason to update the Properties window at run time.
The format of the list represented by attributeList can be one of the following:
  • a list with no named items that is passed with the event. All items in the list are processed for the currently selected objects. The items in the list correspond to the attributes whose values must be refreshed.
    If a user selects multiple objects on a frame and updates a common attribute in the Properties window, the “refresh Attributes” event is sent to all selected objects.
    Sample list: ('borderColor', 'backgroundColor', 'borderStyle')
  • a list with named items, where the named items represent the object identifiers that should be refreshed. A named item can point to an attribute or to a list of attributes that should be refreshed for the object that is represented by the identifier. If the named item is set to 0, a period (missing value), or ( ), then all of the attributes are refreshed for the object that is represented by the identifier.
    When you use a list of object identifiers, the event can be sent to all valid objects on the frame. An object does not have to be selected.
    For example, a list can include
    (2324= 0, 3345=('selectedItem', 'items', 'comboboxStyle'),
     7272='text')
    All attributes would be refreshed for the object whose identifier is 2324; selectedItem,items, and comboxStyle would be refreshed for the object whose identifier is 3345; and text would be refreshed for the object whose identifier is 7272. Invalid attribute names would be ignored.
If no list parameter is passed with the event, then the entire list of attributes is refreshed for the selected object.
Note: It is the responsibility of the component developer to use the “refresh Attributes” event appropriately. For example, you should not refresh the attribute that the setCAM is updating, because the _setAttributeValue method call will not be completed during the CAM operation.

Example

As an example of using the “refresh Attribute” event due to a change in another attribute, consider a subclass of sashelp.fsp.object.class that has a character attribute named testMode and a numeric attribute named newValue. If the testMode attribute is set to Test, then the attribute value of newValue should be set to 999and its editable status should be changed to No. If the value of testMode is set to anything other than Test, then newValue should be Editable=Yes and its value should remain unchanged.
To create the setCAM that sends the “refresh Attributes” event to implement the class:
  1. Create a new class whose parent is sashelp.fsp.object.class and whose description is Testing Object.
  2. Save the class as sasuser.test.testing.class.
  3. In the Attributes node of the Class Editor, select New Attribute from the pop-up menu and add a character attribute named testMode. Add a numeric attribute named newValue.
  4. In the Set CAM cell, select the setcamTestMode method from the drop-down list. When you are prompted to add the method, click Yes.
  5. In the New Method dialog box, click Source and add the following code to the sasuser.test.testing.scl entry:
    USECLASS sasuser.test.testing.class;
    setcamTestMode:  method
       attrval:char return=num;
       dcl list changeAttrList = makelist();
       dcl list refreshList = makelist(); 
       dcl num rc;
       /* set value and change editable status if value='Test' */
       if (upcase(attrval)='TEST') then do;
          rc = insertc(changeAttrList,'No',-1,'editable');
          _setAttributeValue('newValue',999);
       end;
       else
          rc = insertc(changeAttrList,'Yes',-1,'editable');
    
       _changeAttribute('newValue',changeAttrList);
    
       /* refresh datalist displayed in Property Window */
       rc = insertc(refreshList,'newValue',-1);
       _sendEvent('refresh Attributes',refreshList);
       rc = dellist(refreshList);
       return (0);
    endmethod;
    enduseclass;
  6. Compile and save the code, close the Source window, and then close the New Method dialog box.
  7. Save the class as sasuser.test.testing.class and close the Class Editor.
You could then use the Testing class in a frame:
  1. In the SAS Explorer, select a catalog, and then select Filethen selectNew and specify a FRAME entry.
  2. In the Components window, right-click and select Add Classes from the pop-up menu to add sasuser.test.testing.class. If the Components window is not displayed when the new frame appears in the Build window, then select Viewthen selectComponents Window to display the Components window.
  3. Drag an instance of the Testing object and drop it onto the frame.
  4. Select Viewthen selectProperties Window and select the testing1 component in the tree.
  5. Test the CAM:
    • Change the value of testMode to Test. The value of newValue changes to 999 and the attribute is not editable.
    • Change the value of testMode to any value other than Test. The value of newValue is editable.