HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Generalize code that populates MFC list control?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
controlpopulatesgeneralizemfcthatcodelist

Problem

I'm using the Model View Presenter (MVP) pattern in MFC that's not hugely relevant to my question but I mention it for context. I have some code that is designed to populate a list control with data from a list.

I have two list boxes which have almost the same code except the type of list is different and the function used to actually put items in the list control is different. So my questions are:

  • How can I genericize this member function so that I could pass it an arbitrary list of objects, and a population function (i.e., what AddCustomerToListControl is)?



  • Besides genericizing it are there other improvements to be made?



(Note the calls to SetTopIndex are so that the scroll position is remembered.)

void MyDialog::SetCustomerList(const std::list& customers)
{
    customersListCtrl_.SetRedraw(FALSE);

    int selectedItemIndex = customersListCtrl_.GetNextItem(-1, LVNI_SELECTED);
    int topIndex = customersListCtrl_.GetTopIndex();

    customersListCtrl_.DeleteAllItems();

    if(customers.size() > 0)
    {
        for(std::list::const_iterator it = customers.begin();
                it != customers.end() ; it ++)
        {
            AddCustomerToListControl(*it);
        }
        customersListCtrl_.SetItemState(selectedItemIndex,LVIS_SELECTED, LVIS_SELECTED);
    }

    customersListCtrl_.SetTopIndex(topIndex);
    customersListCtrl_.SetRedraw(TRUE);
}


UPDATE

Another detail is the the function AddCustomerToListControl above needs a reference to the listControl in order to add items to it (e.g., call InsertItem and SetItemText)

Solution

To Generalize it:

class MyDialog
{
    template
    void SetCustomerList(T const& customers, A action);
    ....
};

template
void MyDialog::SetCustomerList(T const& customers, A action)
{
    .....
    // AddCustomerToListControl(*it);
    action(*it);
    .....
}

// At call point:
SetCustomerList(customers, &AddCustomerToListControl);


Other Changes:

You can use the standard algorithms:

for(std::list::const_iterator it = customers.begin();
            it != customers.end() ; it ++)
    {
        AddCustomerToListControl(*it);
    }


Can be replaced with:

std::for_each(customer.begin(), customer.end(), AddCustomerToListControl);
    // or in the new code:
    std::for_each(customer.begin(), customer.end(), action);

Code Snippets

class MyDialog
{
    template<typename T, typename A>
    void SetCustomerList(T const& customers, A action);
    ....
};


template<typename T, typename A>
void MyDialog::SetCustomerList(T const& customers, A action)
{
    .....
    // AddCustomerToListControl(*it);
    action(*it);
    .....
}

// At call point:
SetCustomerList(customers, &AddCustomerToListControl);
for(std::list<Customer*>::const_iterator it = customers.begin();
            it != customers.end() ; it ++)
    {
        AddCustomerToListControl(*it);
    }
std::for_each(customer.begin(), customer.end(), AddCustomerToListControl);
    // or in the new code:
    std::for_each(customer.begin(), customer.end(), action);

Context

StackExchange Code Review Q#5634, answer score: 3

Revisions (0)

No revisions yet.