ListCtrl Operations





3.00/5 (2 votes)
Add, Update, Delete operations on the ListCtrl.
Introduction
Hello Guys. This is my first ever article on CodeProject (or anywhere else) so I hope you don’t mind anything unusual.
This is a beginner’s article for adding, updating and deleting items froma ListCtrl in MFC Dialog based application.
Solution
First thing first, we make a standard MFC Dialog based application and make the GUI as you desire. Then we add the following variables to the controls.
- Right click
StudentId
editbox and clickAdd Variable.
In Category: select Value and name variable as: m_sStudentId. Type is CString. - Right click
Name
editbox and clickAdd Variable
. In Category: select Value and name variable as: m_sName. Type is CString. - Right click
ListCtrl
and clickAdd Variable
. In Category: select Control and name the variable as: m_ListOperations. - Go to the properties of ListCtrl and make sure that View property is set to: Report
- Finally you can
add three event handlers to the three buttons. Name them as you desire. I have
OnAddItem(), OnUpdateItem(),
OnDeleteItem().
Now starting with the solution, it has four main functions
namely: AddColumns_ToList()
, AddItem()
, UpdateItem()
and DeleteItem()
.
Their names describe what they are meant to do. Here is the
function body of AddColumns_ToList()
. It is called in OnInitDialog()
.
void CListCtrl_CommonActionsDlg::AddColumns_ToList()
{
m_ListOperations.SetExtendedStyle(LVS_EX_GRIDLINES);
LVCOLUMN col;
int nCol;
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.cx = 70;
col.pszText = _T("ID");
nCol = m_ListOperations.InsertColumn(0, &col);
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.cx = 170;
col.pszText = _T("Name");
nCol = m_ListOperations.InsertColumn(1, &col);
}
Now here is the body for adding the items to the list. Remember that you are taking values from two editboxes.
void CListCtrl_CommonActionsDlg::AddItem()
{
UpdateData();
LVITEM item;
int nItem;
item.mask = LVIF_TEXT;
item.iSubItem = 0;
//If 'm_listListOperations.GetItemCount() <= 0' evaluates to TRUE then 0,
//else value returned by 'm_listListOperations.GetItemCount()'
item.iItem = (m_ListOperations.GetItemCount() <= 0) ? 0 : m_ListOperations.GetItemCount();
item.pszText = m_sStudentId.GetBuffer(1024); //insert the StudentId from editbox to item
nItem = m_ListOperations.InsertItem(&item);
m_ListOperations.SetItemText(nItem, 1, m_sName); //second column of the ListCtrl
GetDlgItem(IDC_STUDENTID)->SetWindowTextW(_T(""));
GetDlgItem(IDC_NAME)->SetWindowTextW(_T(""));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
And now we update the record. For this, we use a
structure named LVFINDINFO.
We use
the ListCtrl’s
FindItem()
method to find the item using the Id we get
from the editbox. Using this methos, if the item is found then its information
will be stored in the LVFINDINFO
structure and it then returns an index
of the found item. Here is how it is done.
void CListCtrl_CommonActionsDlg::UpdateItem()
{
UpdateData();
LVITEM item;
int nItem;
CString str;
GetDlgItem(IDC_STUDENTID)->GetWindowTextW(str);
if (str != "")
{
LVFINDINFO info;
info.flags = LVFI_PARTIAL|LVFI_STRING;
info.psz = str.GetBuffer(1024);
CString arr[3];
arr[0] = str;
arr[1] = m_sName;
int index = m_ListOperations.FindItem(&info);
if(index >= 0)
{
CHeaderCtrl* column = (CHeaderCtrl*)m_ListOperations.GetDlgItem(0);
//OR: CHeaderCtrl* column = m_listListOperations.GetHeaderCtrl();
int cols = column->GetItemCount();
item.mask = LVIF_TEXT;
item.iItem = index;
item.pszText = m_sStudentId.GetBuffer(1024);
int nItem = index;
for (int i=0; i<cols; i++) //loop through the columns
{
if(i==0)
continue; //continue: because we do not want to update the first column
else
m_ListOperations.SetItemText(nItem, i, arr[i]); //update the value
}
GetDlgItem(IDC_STUDENTID)->SetWindowTextW(_T(""));
GetDlgItem(IDC_NAME)->SetWindowTextW(_T(""));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
else
{
MessageBox(_T("No Item Found !!!"));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
}
else
{
MessageBox(_T("No Number Entered !!!"));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
}
And now we delete the record. This is almost same as the previous function, the functionality being a different one. We have to find the item first and once found, we can delete it. Here is it
void CListCtrl_CommonActionsDlg::DeleteItem()
{
CString str;
GetDlgItem(IDC_STUDENTID)->GetWindowTextW(str);
if (str != "")
{
LVFINDINFO info;
info.flags = LVFI_PARTIAL|LVFI_STRING;
info.psz = str.GetBuffer(1024);
int index = m_ListOperations.FindItem(&info);
if(index >= 0)
{
m_ListOperations.DeleteItem(index);
GetDlgItem(IDC_STUDENTID)->SetWindowTextW(_T(""));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
else
{
MessageBox(_T("No Item Found !!!"));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
}
else
{
MessageBox(_T("No Number Entered !!!"));
GetDlgItem(IDC_STUDENTID)->SetFocus();
}
}
So this is how we add, update and delete items from a ListCtrl. Simple, isn’t it?
Points to Remember
- There could have been a lot of checks before doing these operations. For example: checking whether an ID already exists before we can add it to ListCtrl. But since the motive was to keep this sample as simple as possible, I think other such actions should not be a problem
- Please be aware that I do not know any drawbacks that this solution has. It just does the job for me perfectly. If there are any drawbacks, please share so that others may know whether to use this or not.