Introduction
I have Created this UserControl for those who are looking for DataGridView paging functionality. So many times we are using DataGridView in our Windows application with paging. So my intention for this article is to show User Control creation and To provide DataGridView with paging functionality.
Although Creating paging functionality is very basic. but i want to show you features of UserControls through this article and i think this would be the best topic to learn user control. People already know about DataGridView and Paging so there won't be any additional knowledge required to understand the functionality.
How it will look ?
Let me show you first how this control will look like, this way you know that what you are going to develop.
Creating UserControl:
I hope you already know about how drag and drop your button, label or textbox control on your window forms. You may have added so many Forms in your project. similarly you can Add new UserControl from "RightClick on project >Add > New Item". Or if you want to create UserControl for that can be used by other application then you can Add New Windows Form Control Library Project. Once you build your application it will provide you DLL(Dynamic Link Library) file to use in other projects.
As you can see above we have couple of button controls, one textbox control and one DataGridView control. We have set DataGridView Dock
property to Fill so it will look perfect even if we change the width and height of our UserControl. On bottom side we have created one TableLayoutPanel
Which will be used to arrange our buttons and textbox properly. TableLayoutPanel Dock
property is set to bottom with fixed height. so it will not break our design even after resizing the control. After changing look and feal of the user control, you can now proceed for the code behind part of the control.
I think this introduction is enough for now. Let's check code of DataGridView UserControl.
We need to expose some properties in UserControl so other people can modify it. Example : Width of DataGridView, Height of DataGridView, Button Text, PageSize, DataSource etc.
Let we start with looking at the code of exposing UserControl properties. First of all we will look at the most important properties like PageSize.
private int _PateSize = 10;
public int PageSize
{
get
{
return _PateSize;
}
set
{
_PateSize = value;
}
}
PageSize property is very important and without that we can not set how many rows we would like to see per page. We have set default value of pagesize to 10. if you do not set the value of the page size then it will display 10 rows per page.
Now next will look at the DataSource property of the control. this control consist of the DataTable that we have bind with the DataGridView. alghough this is not much important property but we have created in case user want all the data instead of paged data.
private DataTable _DataSource;
public DataTable DataSource
{
get
{
return _DataSource;
}
set
{
_DataSource = value;
}
}
Other properties like Width and Height is also important to set size runtime. alghough user can change width and height of the control using design time but we can add it as a property so runtime it can be set.
private int _Width;
public int ControlWidth
{
get
{
if (_Width == 0)
return dataGridView1.Width;
else
return _Width;
}
set
{
_Width = value;
dataGridView1.Width = _Width;
}
}
private int _Height;
public int ControlHeight
{
get
{
if (_Height == 0)
return dataGridView1.Height;
else
return _Height;
}
set
{
_Height = value;
dataGridView1.Height = _Height;
}
}
just for your note, i have added some validation for Height, Width Button Text property. We need such validation to reduce possibility
of error message. If user try to get Height value before setting it then
it will gives you incorrect result (value 0). so we have added such
validation in above properties.
And at last we will expose button text properties. Normally we are familier with paging button as First, Previous, Next and Last but instead some user want to display that control with different text like greterthen(>) or Lessthen(<) sign. so that can be set by below properties. Although below four properties are not much important but it's depend upon the choice of user.
private string _FirstButtonText = string.Empty;
public string FirstButtonText
{
get
{
if (_FirstButtonText == string.Empty)
return btnFirst.Text;
else
return _FirstButtonText;
}
set
{
_FirstButtonText = value;
btnFirst.Text = _FirstButtonText;
}
}
private string _LastButtonText = string.Empty;
public string LastButtonText
{
get
{
if (_LastButtonText == string.Empty)
return btnLast.Text;
else
return _LastButtonText;
}
set
{
_LastButtonText = value;
btnLast.Text = _LastButtonText;
}
}
private string _PreviousButtonText = string.Empty;
public string PreviousButtonText
{
get
{
if (_PreviousButtonText == string.Empty)
return btnPrevious.Text;
else
return _PreviousButtonText;
}
set
{
_PreviousButtonText = value;
btnPrevious.Text = _PreviousButtonText;
}
}
private string _NextButtonText = string.Empty;
public string NextButtonText
{
get
{
if (_NextButtonText == string.Empty)
return btnNext.Text;
else
return _NextButtonText;
}
set
{
_NextButtonText = value;
btnNext.Text = _NextButtonText;
}
}
Now Let's Look at the Second portion of our code, i.e. Binding of the DataTable with the DataGridView. Here we need to filter our data according to current page. We also need to change the textbox information that shows where our current page is.
public void DataBind(DataTable dataTable)
{
DataSource = dataTable;
dataGridView1.DataSource = ShowData(1);
}
When user bind the DataTable with the our customized DataGridView, we need to show them very first page from all the data. so we have pass parameter 1 in the ShowData private function. Above function will internally call the ShowData function and it will Create new DataTable dynamically.
private DataTable ShowData(int pageNumber)
{
DataTable dt = new DataTable();
int startIndex = PageSize * (pageNumber - 1);
var result = DataSource.AsEnumerable().Where((s, k) => (k >= startIndex && k < (startIndex + PageSize)));
foreach (DataColumn colunm in DataSource.Columns)
{
dt.Columns.Add(colunm.ColumnName);
}
foreach (var item in result)
{
dt.ImportRow(item);
}
txtPaging.Text = string.Format("Page {0} Of {1} Pages", pageNumber, (DataSource.Rows.Count / PageSize) + 1);
return dt;
}
ShowData method have different portion of the code. First of all it will take pageNumber as the parameter. Suppose user requirest for the 3rd numbe of page then first of all it will check for how many records from DataSource it need to return. ShowData function will return DataTable with the DataRow count as PageSize. In case you have last page with 5 records then DataTable will be filled with 5 DataRows only. Let's look at the above code one by one.
if you see the 3rd line of the ShowData function, we have used DataSource which contains all the records of in form of DataTable. To fire a LINQ query on the DataTable first of all you need to cast it as Enumerable. AsEnumerable will convert our DataTable into Enumerable type. then you can apply indexed based Where condition. (s,k) in the where condition denotes DataRow(s) and Index(k) respectively. if user request for the 3rd page and page size is 10 then startIndex would be 20. on 3rd page we need to show data from 21 to 30. But DataRows are stored as index based so we need to fetch records from 20th to 29th (20th and 29th row will be included). So the where clause says that retrun the records starting from 20 to (20+10=30). But on right size operation we have used (<)greterthen sign insted of (<=)greter then or equal to. so 30th record will not be return.
Then next foreach loop will create DataColumns in DataGridView. if you do not create datacolumn in the DataGridView then it will not show you the data correctly.
And on the last foreach loop we are importing required rows in new DataTable i.e. dt. We can not directly add item like dt.Rows.Add(item) because that datarow is already associated with other DataTable. So here we have used dt.ImportRow(item).
When user click on the First button we need to display the first page starting form 0th index to PageSize
. As you can see in the btnFirst_Click event we have added checking for _CurrentPage
. if user is already on the First page, clicking the first button doesn't make any sense. So we have added one MessageBox showing the information. if _CurrentPage
is not first page then we set it to first and then call the ShowData function internally and bind the DataSource of DataGridView.
private void btnFirst_Click(object sender, System.EventArgs e)
{
if (_CurrentPage == 1)
{
MessageBox.Show("You are already on First Page.");
}
else
{
_CurrentPage = 1;
dataGridView1.DataSource = ShowData(_CurrentPage);
}
}
Next button will navigate the DataGridView data on the next page. So DataGridView updates it data accordingly. when user click the Next button lastPage will be calculated becuase, if user is already on the last page then we should prompt some message that your requested page is not exist or you are already on the last page, you can not navigate to the next page. if requested page is not the last page then we increment the CurrentPage and call the ShowData function.
private void btnNext_Click(object sender, System.EventArgs e)
{
int lastPage = (DataSource.Rows.Count / PageSize) + 1;
if (_CurrentPage == lastPage)
{
MessageBox.Show("You are already on Last page, you can not go to next page of Last page.");
}
else
{
_CurrentPage += 1;
dataGridView1.DataSource = ShowData(_CurrentPage);
}
}
Previous button will navigate the DataGridView to the previous page. it means if you are on the 3rd page then clicking previous button will show you the data of the 2nd page. we also need to make sure if user is already on the first page, there is no previous page of the first page. if requested page is not the first page then decrement the _currentPage
value and call the ShowData function.
private void btnPrevious_Click(object sender, System.EventArgs e)
{
if (_CurrentPage == 1)
{
MessageBox.Show("You are already on First page, you can not go to previous of First page.");
}
else
{
_CurrentPage -= 1;
dataGridView1.DataSource = ShowData(_CurrentPage);
}
}
Last button click event will navigate the grid data on the last page. To check if user's last requested page is already last page we have to store it in some variable. we have created one local variable previousPage to store the previously requested page. if previous page and the last page index is the same then we should prompt a message saying that user is already on the last page. If user reqest is not for the last page then just pass the last page index to the ShowData function.
private void btnLast_Click(object sender, System.EventArgs e)
{
int previousPage = _CurrentPage;
_CurrentPage = (DataSource.Rows.Count / PageSize) + 1;
if (previousPage == _CurrentPage)
{
MessageBox.Show("You are already on Last Page.");
}
else
{
dataGridView1.DataSource = ShowData(_CurrentPage);
}
}
As you can see in all our button click event we have some Information messages. if you want to customize those messages then you also need to create properties for information messages. I leave this excersice on those who are beginner.
Hope you learn something from above code, your suggestions are welcome. Post your message if you feel something missing in this control.
History
24 August 2012 : Initial Release