How to add paging to DataGrid in Silverlight

by Naveen 24. February 2010 10:23

Download Sample Project (367.89 kb)

paging in silverlight datagrid

In one of my previous posts How to use DataGrid in Silverlight I showed a very simple usage where data grid was bound to a list of products. Now let us take one more step in customizing use of this data grid. When I executed my method to get list of products from AdventureWorks database, it returned me about 1000 records. And then datagrid was bound to that list, i got a huge page with grid showing all the records. I am sure at this point you are looking for way to add some kind of paging to your data grid so that user can navigate the list easily.

Silverlight has a control named DataPager that comes in very handy to add paging functionality to any control that you use to display lists. From the name is it obvious that this control is a pager. Following XAML shows how I added paging functionality to my datagrid.


<StackPanel x:Name="ContentStackPanel" Orientation="Vertical">
 <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" 
     Text="Products"/>
  <data:DataPager x:Name="ProductsPager" 
    PageSize="10" 
    DisplayMode="Numeric" 
    AutoEllipsis="True" 
    HorizontalAlignment="Left" />
  <data:DataGrid x:Name="ProductsGrid">
   <data:DataGrid.Columns>
   <data:DataGridTemplateColumn>
   <data:DataGridTemplateColumn.CellTemplate>
   <DataTemplate>
   <StackPanel>
   <Button x:Name="UpdateButton" Content="Update" 
     Click="UpdateButton_Click"></Button>
   </StackPanel>
   </DataTemplate>
   </data:DataGridTemplateColumn.CellTemplate>
   </data:DataGridTemplateColumn>
   </data:DataGrid.Columns>
   </data:DataGrid>
</StackPanel>

You can read more about different ways to customize the display of datapager from the documentation. For this discussion you can see that I have set PageSize, DisplayMode, AutoEipsis and HorizontalAlignment properties of pager and the screen shot shows how it looks. I will talk more about customization of DataPager in detail in next post. For now I just want to keep it to simple use.

PageViewCollection

This is the collection object that drives the functionality for DataPager. In general you need a collection that implements IPagedViewCollection interface. No, you do not have to do any more implementation to get DataPager to work. We already have list of products obtained from previous web service call. You can simply wrap that list into PagedViewCollection object and set it as Source for DataPager object. And then set the source for DataGrid as this PagedViewCollection object and we are all set to go. Following code shows simple change I made in code from previous sample project.


void GetProductsCompleted(object sender, GetProductsCompletedEventArgs e)
{
 _products = e.Result;
 if (null != _products)
 {
  _pagedProductsView = new PagedCollectionView(_products);
  ProductsPager.Source = _pagedProductsView;
  ProductsGrid.ItemsSource = _pagedProductsView;
 }
}

Add References

PagedViewCollection is defined in System.Windows.Data assembly. So you will need to add reference to this assembly in your Silverlight project and then add using directive for the namespace in your source code to refer to the classes in this namespace and assembly.

Adding Paging to DataGrid in Silverlight is as easy as that.

Give your advice to big bosses and make money

Views: 2112

Tags: ,

DataGrid | Silverlight

How to add buttons to Silverlight DataGrid?

by Naveen 11. February 2010 15:36

Download Sample Project

In the previous post How to use Silverlight DataGrid I discussed simple use of DataGrid in Silverlight application. Now it is time to start putting together implementation that we have from day to day to applications. One of the tasks that you may come across is that you need to add buttons to each row in the DataGrid and then handle click events for those buttons. In the previous post I mentioned use of DataGridTemplateColumn to provide custom rendering of columns in the grid. So to add button(s) to your column, you will use the template column and then provide Button control to add them to each row. Following snippet shows how it looks like in my sample application.


<data:DataGrid x:Name="ProductsGrid">
 <data:DataGrid.Columns>
  <data:DataGridTemplateColumn>
  <data:DataGridTemplateColumn.CellTemplate>
   <DataTemplate>
    <StackPanel>
     <Button x:Name="UpdateButton" Content="Update" 
        Click="UpdateButton_Click"></Button>
    </StackPanel>
   </DataTemplate>
  </data:DataGridTemplateColumn.CellTemplate>
 </data:DataGridTemplateColumn>
 </data:DataGrid.Columns>
</data:DataGrid>

Handling Click Event For Button In DataGrid

As you can see from the XAML above, I just added handling of Click event on Button control. And in the codebehind provided implementation for it.


private void UpdateButton_Click(object sender, RoutedEventArgs e)
{
 var ctl = e.OriginalSource as Button;
 if (null != ctl)
 {
  var product = ctl.DataContext as Product;
  if (null != product)
  {
   var msg = string.Format("{0}, {1}, {2}", 
      product.ProductID, product.Name, product.ListPrice);
   MessageBox.Show(msg);
  }
 }
}

Accessing Data Associated With Row In DataGrid

When user clicks on the button in datagrid row, the method gets called. Next question you have is how do you access the data associated with the row on which button was clicked. It is very straight forward. When DataGrid rendering takes place, each control in the row is bound to DataContext. This DataContext is the data that was used to render that row. So you simple look at DataContext property of Button control that raised the event and got the actual data object used for that row.

I think this should give you a good starting point on how to add buttons or some other controls in DataGrid rows and how to access data for them as well. In next post I will discuss more of customization of Silverlight DataGrid.

Give your advice to big bosses and make money

Views: 2101

Tags: ,

DataGrid | Silverlight

How to use DataGrid in Silverlight

by Naveen 5. February 2010 06:58
DataGrid is one of the most important control when it comes to displaying tabular kind of data. We all implement rendering of such data in some of table format. Developers who has been using ASP.Net are very familiar with controls like DataGrid and GridView. Good news is that there is equivalent DataGrid control for Silverlight as well. And for most part it is used the same way as you do in ASP.Net but with different syntax and different way of customizing display of it. In this post I am going to show a very plain and simple use of DataGrid control in Silverlight and then in subsequent posts I will build on top of this post to show some more advanced uses of DataGrid control.

Silverlight Tool Kit

You may already know this and already has it on your development machine, but I will mention it for sake of completness. You are going to need Silverlight Toolkit to use DataGrid. Yes, the control is not part of core Silverlight. Microsoft has developed it as part of the tool kit that has lot of usefull controls. You can read more about this tool kit and controls on the site. For now, down the toolkit and install it on your machine.

Reference assemblies

In your Silverlight project, you will need to add reference to System.Windows.Controls.Data assembly. This is the assembly where DataGrid control is defined. Now you can include DataGrid control on your XAML file. If you tried to add mark up like below on your page, you are going to get error telling you that DataGrid is not recoganized.


<DataGrid x:Name="MyGrid" />

You have to treat DataGrid control like a UserControl in ASP.Net where you have to specify a tag prefix and assembly on top of your page to indicate use of that control. In Silverllight you do this my including xml namespace tag for that silverlight control. In my case I have the following xmlns entry on my XAML file.


xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

This tells the application that I am going to use prefix data for the controls that are present in assembly System.Windows.Controls.Data. Based on this you can now add the following like of mark up on XAML file to include DataGrid on your page.


<data:DataGrid 
  x:Name="CommentsGrid" 
  Height="300" 
  AutoGenerateColumns="True" 
  IsReadOnly="True">
</data:Grid>

Attach To Data Source

Now that we have included DataGrid control on the page, we need to attach it to some data source to show some results. Very much like ASP.Net, you will attach an enumeration to this control. The difference is that here it is done through property name ItemSource. Following line of code shows how it is done for silverlight DataGrid control.


List<Comment> unmoderatedComments = new List<Comment>();

void BindGrid()
{
 CommentsGrid.ItemsSource = unmoderatedComments;
}

As you can see that DataGrid is bound to a List of Comment objects. So far so good, very much like your ASP.Net DataGrid or GridView.

Columns to Display

In the mark of DataGrid above, I have explcitly set AutoGenerateColumn property to true. This actually is default value. What this means is that when DataGrid is bound to the collection, it will generate column for each data field or property for the objects in the collection and display them. Thsi is same behavior you see in ASP.Net data grid.

Explcitly specifying Columns

When you are dealing with some real application most of the time you control the columns you want to display and how you want to display them. Silverlight DataGrid does allow you to do so. Fisrt, you will set AutoGenerateColumns property to false. Following mark up shows how you will specify the columns that you want to display.


<data:DataGrid x:Name="CommentsGrid" Height="300" 
  AutoGenerateColumns="False" IsReadOnly="True">
 <data:DataGrid.CellStyle>
  <Style TargetType="data:DataGridCell">
  <Setter Property="VerticalAlignment" Value="Top"></Setter>
  </Style>
 </data:DataGrid.CellStyle>
 <data:DataGrid.Columns>
  <data:DataGridTextColumn Header="Comment Date" 
    Binding="{Binding CommentDate}"></data:DataGridTextColumn>
  <data:DataGridTextColumn Header="Comment Text" Binding="{Binding Text}">
  <data:DataGridTextColumn.ElementStyle>
  <Style TargetType="TextBlock">
   <Setter Property="TextWrapping" Value="Wrap"/>
  </Style>
  </data:DataGridTextColumn.ElementStyle>
 </data:DataGridTextColumn>
 <data:DataGridTemplateColumn>
  <data:DataGridTemplateColumn.CellTemplate>
   <DataTemplate>
    <StackPanel Orientation="Horizontal">
     <Button x:Name="ApprovedButton" Content="Approved" 
       Click="ApprovedButton_Click" Height="30" Margin="3"></Button>
     <Button x:Name="DeleteButton" Content="Delete" 
        Click="DeleteButton_Click" Height="30" Margin="3"></Button>
     <Button x:Name="SpamButton" Content="Mark Spam" 
       Click="SpamButton_Click" Height="30" Margin="3"></Button>
   </StackPanel>
   </DataTemplate>
  </data:DataGridTemplateColumn.CellTemplate>
 </data:DataGridTemplateColumn>
 </data:DataGrid.Columns>
</data:DataGrid>

You will need to add Columns section under your DataGrid control definition and then specify each column that you would want to display. And to bind the column to particular property or field, you will use Binding property. For this post I am going to keep the dicussion to simple binding of the column to property of the object. I will discuss more advanced use in subsequent posts. You can see it is very similar to how you are used to doing things in ASP.Net.

And to accomodate more customized view of the column, you will use DataGridTemplateColumn where you can layout the template of the view of that column. This is also similar to template column in ASP.Net.

More...

For this post I am going to leave this discussion to this simple display of data. I will be discussing more about use of Silverlight DataGrid in subsequent posts. This post should get you started with use of it now.

Give your advice to big bosses and make money

Views: 1894

Tags: ,

DataGrid | Silverlight

How to format GridView or DataGrid Using JQuery

by Viper 14. July 2009 14:12
datagrid using jquery

Download Sample Project

This is based on a question asked by one of my blog readers.

I have 2 datagrids. Each Grid has the same amount of columns and each grid has a select column as the last column on the right added from the "gridview/ edit Columns/ CommandField/ Add" sequence. The first GridView has the Select column as a Link The second GridView has the select Column as a button I want to be able to change the text for both the Link and button in cell(4), setting them to the value in cell(1) from the same row using the GridView_RowDataBound event. However, using "cell(4).text = cell(1).text" just overwrites the text value removing the hyperlink and button.

The behavior described in this question is as expected. When you set text of a cell in grid, it directly affects HTML that is going to be rendered. When you set text value of a cell, it means that you are setting innerText of the cell. The column that GridView creates for command fields (Edit, Delete and Select) are a (anchor) or button elements. So you can see what will happen if you set text value in that cell. It will wipe out those link or button controls and replace them with simple text string.

There are properties like EditText, DeleteText and SelectText for CommandField column in grid view. If you try to set these values using a server side method by passing it DataContainer object, you will get following exception thrown.


Databinding expressions are only supported on objects that have a DataBinding event. 
System.Web.UI.WebControls.CommandField does not have a DataBinding event.

After looking at the requirements, i realized that requirements are as simple as replacing text with value from another cell in the same row. There is no need for doing any server side tricks or things like that. I can simple put together a simple client side java script that will take values from cell 1 and put them in whatever cell I want. Abd I came up with this small javascript solution using jQuery. This small code snippet shows how you can manipulate GridView or DataGrid on client side using jQuery. Let me show you the client side javascript that I added on the page. Then I will explain what this code is doing.


<script type="text/javascript">
function updateCommandLinks() {
 var $gridTable = $('#productsGrid');
 var rows = $gridTable.find('tbody > tr');
 var slicedRows = rows.slice(1, rows.length - 2);
 slicedRows.each(function() {
  var cells = $(this).find('td');
  var cellElem1 = cells.get(1);
  var cellElem5 = cells.get(5);
  $(cellElem5).find('a').each(function() {
   $(this).addClass('commandlink').append(" " + cellElem1.innerText);
  });
 });
}

$(document).ready(function() {
  updateCommandLinks();
});
</script>

The above code may look little verbose considering you can write very concise code using jQuery. But for sale of explaining and debugging, I decided to make it little bit verbose. I am sure you can reduce it to half the lines of code that I have written.

The implementation adds a handler for document load event. In that event handler here are the steps it follows:

  1. Finds the element that has id of productsGrid. In our case, that is HTML element ID of our grid view.
  2. In the table, it gets collection of all the rows, identified by tr tag.
  3. Since in my implementation I have header and pager, that adds three rows into the collection. One top row for the header and then the last row itself will contain another table that contains a row for paging elements. To keep it simple, I decided to use slice function to remove first and last 2 rows from collection. You will need to modify this implementation depending on your grid rendering.
  4. It iterates over each row in the collection.
  5. For each row it then finds all cells, identified by td tag.
  6. In my case, I want to replace text in command links with text from second column. So I saved reference to cell at index 1 by using get function.
  7. Then I extracted all elements with tag a from sixth column.
  8. Then it iterates over collection of anchor a tags and appends text from second cell to text in each of the links.

I think that is a simple implementation that serves the purpose without making any changes on the server side. The attached project has the complete implementation for this grid. This is a Visual Studio 2010 project. But you should be able to copy the script from the page to your implementation.

Give your advice to big bosses and make money

Views: 2000

Tags: , , ,

ASP.Net | DataGrid | GridView | JQuery

How to format and modify value in data grid row at run time based on previous row values

by Viper 7. July 2009 14:35
grid view row formatting

Download Sample Project

This was a question was asked by one of my site visitors, Mike. Following is the text of the question:

This is a similar question to one you have already answered in formatting Grid Views. However there are 2 main differences. First: I want to change the value of a column (not the format) in any row if the row preceding it has a certain value in the same column.

This question translates to How do you change value of a data grid column based on values of previous row(s). I generalized this question to cover all previous rows and not just the preceding row. Answer to all such questions relies on handling events like RowDataBound or RowCreated events. When a data grid or grid view renders, RowDataBound fires when row is being data bound and then RowCreated is fired after it has been data bound and row has been created. So depending on at what stage of rendering you want to change behavior of a row, you will subscribe either of these events. In the sample project, I am subscribing to RowDataBound event.

Next step is to access values from previous rows. Here you have choice. One, you can keep some local vaiable that stores values from previous row(s) and then use them in current row event handling. Two, you can access the previous GridRow based on index. In this sample i will discuss the approach of accessing previous row based on index and then extracting values from certain cells.

In RowDataBound event handler, GridViewRowEventArgs provides you access to DataItem associated with current row only. You do not have access to DataItem associated with previous rows. But at this point, previous rows have been prepared for rendering. You have access to all the cell values associated with previous row. You can access GridRow object of previous rows and extract text from cells that you are interested in. In the sample project, I am accessing ListPrice from fourth column and then displaying it in current row along with price associated with current row. Well, this does not sound like something that is very interesting or useful. But it serves the purpose of demonstrating you will accomplish the task.

Here is the code snippet from sample project.


protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
 if (e.Row.RowType == DataControlRowType.DataRow)
 {
  double price = -1.0;
  double prevPrice = -1.0 ;
  // Access the previous row.
  if (e.Row.RowIndex != 0)
  {
   GridViewRow prevRow = this.productsGrid.Rows[e.Row.RowIndex - 1];
   if (null != prevRow && 
    prevRow.RowType == DataControlRowType.DataRow)
   {
    double.TryParse(prevRow.Cells[3].Text, out prevPrice);
   }
  }
  var thisRowData = e.Row.DataItem as DataRowView;
  if (!Convert.IsDBNull(thisRowData["ListPrice"]))
  {
   double.TryParse(thisRowData["ListPrice"].ToString(), out price);
  }
  var ctrl = e.Row.FindControl("prevPriceLabel") as Label;
  if (null != ctrl)
  {
   ctrl.Text = string.Format("{0} - {1}", prevPrice, price);
  }
 }
}

The attached sample project is a VS2010 project. There is no VS2010 or .Net4.0 implementation in the project. So if you are using VS2008 or prior, you should be able to copy the implementation files into your own project.

Feel free to send me any request for any other grid view implementation you would like to be answered or implemented.

Give your advice to big bosses and make money

Views: 2163

Tags: , ,

.Net | ASP.Net | C# | DataGrid

How to insert google map in DataGrid or GridView

by Viper 2. July 2009 05:08

Download Sample Project

While working on a car dealership listings web site, I was experimenting with inserting google maps into the data grid. The grid will show name and address of top rated car dealers in certain categories. And along side their information, it will show their location on google map. To accomplish this task, I needed the longitude and latitude of car dealership's address or location. Some time back in my earlier post Convert Address and/or IP address to Geo Location I described how you can utilize google map's api to convert a physical address to geo location coordinates. This is the same technique that I used in Backyardtweets to show tweets in a specified location. So use the google map api to get these coordinates and insert these coordinates in the java script.

Now that you have geo location corresponding to an address, your task is to insert that little piece of java script in each row of the data grid. The way google map java script works is that it requires a HTML element where it can insert the map image. So I inserted a div with unique id in a cell in each row and then passed that unique id to java script that is used to render the map. Add an event handler for RowDataBound event and there you can add the element and register a client script for map as well. Here is some code snippet that shows how this all is accomplished.


protected void OnDealerRowDataBound(object sender, GridViewRowEventArgs e)
{
 if (e.Row.RowType == DataControlRowType.DataRow)
 {
	var carDealer = e.Row.DataItem as CarDealer;
	var divId = string.Format("dealloc_{0}", carDealer.Id);
	var mapPanel = e.Row.Cells[2].FindControl("mapPanel") as Panel;
	var div = new HtmlGenericControl("div");
	div.Attributes.Add("id", divId);
	div.Attributes.Add("class", "mapdiv");
	mapPanel.Controls.Add(div);
	string js = GetGoogleMapScript(carDealer, divId);
	ScriptManager.RegisterStartupScript
	  (this.Page, this.GetType(), "_map_" + carDealer.Id, js, true);
 }
}

private string GetGoogleMapScript(CarDealer dealer, string ctlId)
{
 string loc = string.Empty;
 if (!string.IsNullOrEmpty(dealer.State))
 {
	loc = string.Format("{0},", dealer.State);
 }
 loc += dealer.Country;
 decimal longitude, latitude;
 GoogleMapUtility.GetGeoLocationFromGoogle(loc, out longitude, out latitude);
 dealer.Location.Latitude = latitude;
 dealer.Location.Longitude = longitude;
 return GetJScriptForGeoLocations(longitude, latitude, ctlId);
}

public static string GetJScriptForGeoLocations(decimal longitude, decimal latitude, string elemId)
{
 StringBuilder sb = new StringBuilder();
 sb.Append("function initialize_" + elemId + "() {{");
 sb.Append(" if (GBrowserIsCompatible()) {{ ");
 sb.Append(" var map = new GMap2(document.getElementById(\"{0}\"));");
 sb.Append(" map.setCenter(new GLatLng({1}, {2}), 13);");
 sb.Append(" map.setUIToDefault();}}}} initialize_" + elemId + "();");
 return string.Format(sb.ToString(), elemId, latitude, longitude);
}

The attached project with this post has all the implementation for this sample implementation. And this is a Visual Studio 2010 project. I have not used any 2010 specific namespaces or code in this implementation so you should be able to take all the code and move it into a VS2008 or VS2005 project. And you will need to get key for google map api use from google as well.

Give your advice to big bosses and make money

Views: 6322

Tags: , ,

ASP.Net | DataGrid | GridView

How to display row number in Row header of DataGrid

by Viper 12. January 2009 08:17

Lot of time you want to display line number (row index) of rows in DataGrid in Row header of your grid very much like how each row in Microsoft Excel displays line number. One dirty solution is to add a new column in the grid at first position and then display its text as row number. There is more elegant solution available. You can actually set the Row.Header value to Row index in LoadingRow event of your grid.

protected GridRowLoading(object sender, DataGridRowEventArgs arg)
{
  arg.Row.Header = arg.Row.GetIndex();
}

Make sure that you set HeaderVisibility property of your grid to "Row" or "All". By default row header is not visible.

Give your advice to big bosses and make money

Views: 3166

Tags:

ASP.Net | Silverlight | DataGrid

Powered by BlogEngine.NET 1.5.1.7
Theme by Naveen Kohli

By Categories