Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

An Adaptable Property List Control

, 25 Apr 2003
Rate this:
Please Sign up or sign in to vote.
An object properties list control than can change based on the objects state.
  • Download demo project - 45 Kb
  • Download source files - 19 Kb

    Sample Image - PropertyListCtrl.gif

    Introduction

    In an application I was developing, there was a need to implement some kind of user interface for changing an objects properties for different types of objects. Some objects properties are static, but there are objects whose properties are changing, reflecting their actual state. So I decided to create a Microsoft Visual Basic like control that can display different property items according to an objects state.

    Lets take a simple example. I need to describe the properties of individual items of a form. The items can display simple text, but also a concrete representation from a database. If the item displays only simple text, I do not need to edit the other parameters (object properties) that specify data field and display format.

    In the sample screen above, the Data and Data format categories will be removed from the properties list when the Data binding item is set to no.

    How it works

    The CPropertyListCtrl class implements the neccessary utility for presenting property items and user interaction.

    The CInPlaceEditImp and CInPlaceComboBox classes implement in place controls for editing item values for strings and for list items or enumerations respectively.

    The property data item classes allow for property data item manipulations.

    The CPropertyItemString and CPropertyItemList are classes for basic editing of property data values.

    The CPropertyItemCategory class contains property items of one category.

    The CPropertyItemManager is a container for all the property categories of an object.

    The CPropertyItemManagerAdaptable class supports the mechanism of adaptibility.

    How to use it

    1. Include the source files into your project.
    2. If you need to you can define your own property list item values (enumerations) derived from the class CPropertyItemList and / or implement your own custom property item value derived from the base class CPropertyItem.
    3. Implement your CPropertyItemManager derived property item manager that describes the property items of your object. If the property items can change according to the objects state, derive your property item manager from the class CPropertyItemManagerAdaptable.
    4. Use the CPropertyListCtrl control in your dialog or view and manipulate its property item manager with the SetPropertyItemManager method.

    How to implement your own property item value class

    Derive it from the base class CPropertyItem and implement its get/set methods and its virtual methods:

    • virtual void DrawValue(CDC* pDC, CRect& rect)
      // for drawing a property item value into the CPropertyListCtrl dc context.
    • virtual void CreateInPlaceControl(CWnd* pWndParent, CRect& rect, CWnd*& pWndInPlaceControl)
      // for creating its own suitable in place control for editing its value.
    • virtual void SetData(CWnd* pWndInPlaceControl)
      // for setting its value after the end of editing by an in place control.
    /////////////////////////////////////////////////////////////////////////////
    // CMyPropertyItem
    
    class CMyPropertyItem : public CPropertyItem
    {
    	CMyPropertyItem(const CMyPropertyItem& d);
    	CMyPropertyItem& operator=(const CMyPropertyItem& d);
    
    protected:
    	DECLARE_DYNAMIC(CMyPropertyItem)
    
    public:
    	CMyPropertyItem(MyDataType myData = INI_VALUE);
    	virtual ~CMyPropertyItem();
    
    	// Attributes
    	MyDataTyp& GetData() const;
    	void SetData(MyDataType& myData);
    
    	// Operations
    	virtual void DrawValue(CDC* pDC, CRect& rect);
    	virtual void CreateInPlaceControl(CWnd* pWndParent, <BR>                                     CRect& rect, CWnd*& pWndInPlaceControl);
    	virtual void SetData(CWnd* pWndInPlaceControl);
    
    	// Data
    private:
    	MyDataType m_myData;
    };
    

    And define its GET_ITEM... and SET_ITEM... macros that are used in a conjuction with the BEGIN_ITERATE_PROPERTY_ITEMS macros. For a better understanding of these look at how they are implemented in the CPropertyItemString or CPropertyItemList classes.

    How to define your own property list item value class

    You can use the predefined macros for implementing classes representing property list item values. In this examle the CMyCustomPropertyItemList is defined with two property items.

    /////////////////////////////////////////////////////////////////////////////
    // CMyCustomPropertyItemList
    
    BEGIN_LIST_ITEM_DATA_TYPE(CMyCustomPropertyItemList)
    	LPCTSTR_STRING_ITEM_DATA(_T("A string value here")),
    	ID_STRING_ITEM_DATA(IDS_STRING_VALUE_FROM_RESOURCES)
    END_LIST_ITEM_DATA_TYPE(CMyCustomPropertyItemList)
    

    Or you can implement your own class, derived from the CPropertyItemList class, overriding its virtual LPCTSTR GetItemData(int nItem) const function.

    /////////////////////////////////////////////////////////////////////////////
    // CMyOwnPropertyItemList
    
    class CMyOwnPropertyItemList : public CPropertyItemList
    {
    	....
    public:
    	virtual LPCTSTR GetItemData(int nItem) const;
    }
    

    How to implement your own property item manager class

    In order for the CPropertyListCtrl control to know what items to display, you have to implement your own property item manager describing the property items of your object. If your object property items are static you simply derive your property item manager from the class CPropertyItemManager and in the constructor declare the items using predefined macros :

    /////////////////////////////////////////////////////////////////////////////
    // CMyStaticPropertyItemManager
    
    CMyStaticPropertyItemManager::CMyStaticPropertyItemManager()
    {
     ////////////////////////////////////////////////////////////General 	
     BEGIN_PROPERTY_TAB(_T("General"), true)
        PROPERTY_ITEM(ID_PD_NAME, CPropertyItemString,<BR>                  _T("Name"), true)
        PROPERTY_ITEM(ID_PD_DESCRIPTION, CPropertyItemString,<BR>                  _T("Description"),true)
        PROPERTY_ITEM(ID_PD_BIND_DATA, CPropertyItemListYesNo, <BR>                  _T("Data binding"), true)
     END_PROPERTY_TAB()
    <BR><BR> <BR> <BR> ///////////////////////////////////////////////////////////////////////
     // Data<BR> BEGIN_PROPERTY_TAB(_T("Data"), true)
        PROPERTY_ITEM(ID_PD_DB_NODE, CPropertyItemString, <BR>                  _T("Db data node"), true)
        PROPERTY_ITEM(ID_PD_HISTORY, CPropertyItemListYesNo, <BR>                  _T("History"), true)
     END_PROPERTY_TAB()
    }
    

    You also need to implement get/set methods for accessing property item values of your object. For simple reference access you can use predefined macros.

    bool CMyStaticPropertyItemManager::SetData(const CObject* pData)
    {
    	const CMyData* pMyData = static_cast <const CMyData* > (pData);
    
    	BEGIN_ITERATE_PROPERTY_ITEMS()
    		SET_ITEM_STRING(ID_PD_NAME, pMyData->m_strName)
    		SET_ITEM_STRING(ID_PD_DESCRIPTION, pMyData->m_strDescription)
    		SET_ITEM_LIST(ID_PD_BIND_DATA, pMyData->m_bBindDatabaseData)
    		SET_ITEM_STRING(ID_PD_DB_NODE, pMyData->m_strDbTableColumn)
    		SET_ITEM_LIST(ID_PD_HISTORY, pMyData->m_bCreateHistoryData)
    	END_ITERATE_PROPERTY_ITEMS()
    
    	return true;
    }
    
    bool CMyStaticPropertyItemManager::GetData(CObject* pData) const
    {
    	CMyData* pMyData = static_cast <CMyData* > (pData);
    
    	BEGIN_ITERATE_PROPERTY_ITEMS()
    		GET_ITEM_STRING(ID_PD_NAME, pMyData->m_strName)
    		GET_ITEM_STRING(ID_PD_DESCRIPTION, pMyData->m_strDescription)
    		GET_ITEM_LIST(ID_PD_BIND_DATA, pMyData->m_bBindDatabaseData)
    		GET_ITEM_STRING(ID_PD_DB_NODE, pMyData->m_strDbTableColumn)
    		GET_ITEM_LIST(ID_PD_HISTORY, pMyData->m_bCreateHistoryData)
    	END_ITERATE_PROPERTY_ITEMS()
    
    	return true;
    }
    

    If you want to implement an adaptable property item manager derive it from the class CPropertyItemManagerAdaptable and define a virtual void OnDataChanged(CPropertyItem* pPropertyItem, CPropertyListCtrl* pWndPropertyListCtrl, int nIndex) method for changing a property items state:

    void CMyAdaptablePropertyItemManager::OnDataChanged(CPropertyItem* <BR>          pPropertyItem, CPropertyListCtrl* pWndPropertyListCtrl, int nIndex)
    {
       bool bDoChecking = false;
    
       switch(pPropertyItem->GetPropertyID())
       {
         case ID_PD_BIND_DATA:
         {
          // Yes/No item
          bool bEnableTabs;
          static_cast <CPropertyItemList*>(pPropertyItem)->GetData(bEnableTabs);
    
          // Enable/Disable tabs 1
          CPropertyItemCategory* pPropertyItemTab = GetCategoryTab(1);
    
          if(pPropertyItemTab->SetEnabled(bEnableTabs))
    	bDoChecking = true;
    			
          // Enable/Disable tabs 2
          int nItemType;
          static_cast<CPropertyItemList*>(pPropertyItemTab->GetPropertyItem(<BR>                                       ID_PD_DATA_TYPE))->GetData(nItemType);
    
          pPropertyItemTab = GetCategoryTab(2);
    
          if(pPropertyItemTab->SetEnabled(bEnableTabs && nItemType < 4))
            bDoChecking="true;" 
          } 
          break;
          case ID_PD_DATA_TYPE: { // Enumerate item 
          { 
            int nItemType; 
            static_cast<CPropertyItemList*>(pPropertyItem)->GetData(nItemType);
    
    	// For items 4 (Form) and 5 (Macro) disable tab #2, for others enable
    	CPropertyItemCategory* pPropertyItemTab = GetCategoryTab(2);
    	bDoChecking = pPropertyItemTab->SetEnabled(nItemType <4); 
           } 
           break; 
           default: 
           return; 
         } 
         if(bDoChecking) 
           CheckState(pWndPropertyListCtrl, nIndex, <BR>                  pPropertyItem->GetPropertyID());
    }
    

    Things to Improve

  • Eliminate flicker while showing in place controls.
  • Add further edit controls.
  • If you have any other suggested improvements, please let me know so that I can incorporate them into the next release. If you want to see how I have used this control in my projects, take a look at http://welcome.to/StefanBelopotocan.
  • License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    Share

    About the Author

    Stefan Belopotocan
    Software Developer (Senior)
    Slovakia Slovakia
    No Biography provided

    Comments and Discussions

     
    GeneralNice work,thanks... Pinmemberucc80130-Jan-06 5:45 
    GeneralScrolling with InPlaceComboBoxImp PinmemberUrban Olars13-Jun-04 10:47 
    GeneralRe: Scrolling with InPlaceComboBoxImp PinmemberUrban Olars29-Jun-04 10:07 
    QuestionExcellent - Can it be used in a commercial app? Pinsussprcarp4-Jun-04 10:33 
    Questionexcellent ! Will it improve ? PinmemberGilles Diawara1-Apr-04 7:55 
    Questionhow can I insert a control into the item? PinsussAnonymous3-Nov-03 22:36 
    GeneralProblems using the control Pinmembersimbakid23-May-03 5:57 
    GeneralRe: Problems using the control PinmemberStefan Belopotocan25-May-03 0:04 
    GeneralRe: Problems using the control Pinmembersimbakid26-May-03 23:01 
    GeneralRe: Problems using the control Pinmembersimbakid27-May-03 23:25 
    Generalprograming the addition of the control PinmemberManuel D. Jiménez23-Jan-03 6:49 
    GeneralRe: programing the addition of the control PinmemberStefan Belopotocan23-Jan-03 21:55 
    GeneralThanks, but... PinmemberManuel D. Jiménez23-Jan-03 22:49 
    QuestionHow to use this control in docking control like workspace PinmemberGuo Yabing20-Dec-02 13:05 
    AnswerRe: How to use this control in docking control like workspace PinmemberStefan Belopotocan23-Jan-03 21:48 
    GeneralBug when more than 256 items PinmemberMephisto7716-Oct-02 21:09 
    GeneralDynamic property item insertion Pinmembersoichi hayashi27-Mar-02 5:41 
    GeneralAnother properties control PinmemberAndreane14-Jan-02 3:53 
    GeneralAdvertising? PinmemberDavid Wulff10-Feb-02 15:02 
    GeneralResizing Issue Pinmembergh7-Nov-01 10:55 
    QuestionHow can I update data? PinmemberMac22-Oct-01 10:51 
    GeneralExcellent Property Control PinmemberRod Hamilton17-Sep-01 13:23 
    Generalgood job! PinmemberBao Nguyen30-Jun-01 10:48 
    GeneralRe: good job! PinmemberManuel D. Jiménez23-Jan-03 0:16 
    GeneralRe: good job! PinmemberBrightLee15-Nov-03 23:37 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Mobile
    Web03 | 2.8.140926.1 | Last Updated 26 Apr 2003
    Article Copyright 2000 by Stefan Belopotocan
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid