Adding dynamic columns in Silverlight Datagrid

This post shows how to add button column to a datagrid(Silverlight) and react to the click event

1.Create a resource for the DataGridtemplateColumn, define CellTemplate
2.After setting the ItemsSource, get the resource we added in step 1 and add it to the grid
 
this is XAML from the page

<UserControl x:Class=”SilverlightApplication1.Page”
    xmlns=”http://schemas.microsoft.com/client/2007
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
    Width=”600″ Height=”600″
             xmlns:data=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”
             xmlns:local=”clr-namespace:SilverlightApplication1;assembly=SilverlightApplication1″>
    <UserControl.Resources>      
        <data:DataGridTemplateColumn Header=”” x:Name=”dtc”>
            <data:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button Click=”Button_Click” Tag=”{Binding CustomerID}”
                            Content=”Delete”></Button>
                </DataTemplate>
            </data:DataGridTemplateColumn.CellTemplate>
        </data:DataGridTemplateColumn>
    </UserControl.Resources>
  
    <Canvas>
        <data:DataGrid x:Name=”dataGrid1″
                       Height=”400″
                       Width=”450″
                       Margin=”0,5,0,10″
                       AutoGenerateColumns=”True” />
        <TextBlock Text=”Sample Text” x:Name=”txt1″
                   Canvas.Top=”500″
                   Canvas.Left=”100″></TextBlock>
    </Canvas>
</UserControl>

let’s say we are getting data from WCF service

the code to call WCF service will look something like this

BasicHttpBinding b = new BasicHttpBinding();
EndpointAddress addr = new EndpointAddress(“http://localhost/mywebsite/MyService.svc“);
ServiceReference1.MyServiceClient client = new SilverlightApplication1.ServiceReference1.MyServiceClient(b, addr);
client.GetCustomersCompleted += new EventHandler<SilverlightApplication1.ServiceReference1.GetCustomersCompletedEventArgs>(client_GetCustomersCompleted);
client.GetCustomersAsync();

 void client_GetCustomersCompleted(object sender, SilverlightApplication1.ServiceReference1.GetCustomersCompletedEventArgs e)
 {           
            this.dataGrid1.ItemsSource = e.Result;
            //this gets the column from the resources and inserts at the beginning of the row
            this.dataGrid1.Columns.Insert(0, this.Resources[“dtc”] as DataGridTemplateColumn);
        }

// this  button click handler sets the text of a Textblock(“txt1”) to customerid of the row in which the button is clicked
 private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.txt1.Text = (sender as Button).Tag.ToString();
        }

22 thoughts on “Adding dynamic columns in Silverlight Datagrid

  1. I tried to use this to add click event handler using code below but got exception at Click=”Button_Click”:

    Failed to assign to property ‘System.Windows.Controls.Primitives.ButtonBase.Click’

    How to fix ?

    Issue 2: In this code column name “PictureColumn” is hard coded. How to set column name in runtime (diffrent grids have different picture property names) ?

    Andrus.

    XAML:

    ….

    C#:

    partial class DataGridBase : DataGrid
    {

    void Create() {
    DataGridTemplateColumn templateCol = new DataGridTemplateColumn();
    templateCol.CellTemplate = (Resources[“dtc”] as DataGridTemplateColumn).CellTemplate;
    Columns.Add(templateCol);
    }

    void Button_Click(object sender, RoutedEventArgs e) { }

    }

  2. XAML was removed from message. Below is xaml with tag characters removed:

    data:DataGrid x:Class=”MyApp.Controls.DataGridBase”
    xmlns:data=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

    data:DataGrid.Resources
    data:DataGridTemplateColumn Header=”” x:Name=”dtc”
    data:DataGridTemplateColumn.CellTemplate
    DataTemplate
    Button Click=”Button_Click”
    Image Source='{Binding PictureColumn, Converter={StaticResource myImageConverter}}’/
    /Button

    /DataTemplate
    /data:DataGridTemplateColumn.CellTemplate
    /data:DataGridTemplateColumn
    ….

    1. Hi,
      Do you have the click handler in the code behind?. Did you try to create the datatemplate in code and assign it, so that you could create the binding at runtime.

  3. There is click handler in DataGridBase class as shown in code sample:

    void Button_Click(object sender, RoutedEventArgs e) { }

    If DataTemplate is created in code using XamlReader.Load exception occurs telling that click handler cannot set in string used as Load parameter. I dont know how to define CellTemplate directly in resource. So this sample code assigns resource form Xaml file using

    (Resources[“dtc”] as DataGridTemplateColumn).CellTemplate

      1. xaml is in DataGridBase.xaml file.
        Click handler is in DataGridBase.xaml.cs file.
        This is like in your sample. So this shoud work.
        Maybe assigning part using line (Resources[“dtc”] as DataGridTemplateColumn).CellTemplate
        breaks this.

          1. I’m loading datatemplate from a resource, not from string:

            DataGridTemplateColumn templateCol = new DataGridTemplateColumn();
            templateCol.CellTemplate = (Resources[“dtc”] as DataGridTemplateColumn).CellTemplate;
            Columns.Add(templateCol);

        1. looks like that has the same effect as loading from a string. I guess you have to find another way of doing that

          1. I tried take the eventhandler from xaml out and add a click event handler in the loadingrow event, I it is not going to the event handler. Not sure of any other options

  4. Hi Friends,
    Please help me I am writing given method in SilverLight 3. but this method is not
    Working properly where I am wrong? I have not more experience in silverlight.i think DataSet is not available in silverlight.

    public class Search
    {
    public void bindDataGrid(DataGrid dg, XDocument xDoc, string DescendantsName)
    {
    if (xDoc.Descendants(DescendantsName).Count() > 0)
    {
    var Xel = from xe in xDoc.Descendants(DescendantsName) select xe;
    foreach (var xe in Xel.Elements())
    {
    DataGridTextColumn col = new DataGridTextColumn();
    col.Header = xe.Name.LocalName;
    System.Windows.Data.Binding bnd = new
    System.Windows.Data.Binding();
    bnd.ConverterParameter = xe.Name.LocalName;
    col.Binding = bnd;
    dg.Columns.Add(col);
    }
    var result = new List();
    foreach (var element in xDoc.Descendants(DescendantsName))
    {
    foreach (var column in element.Elements())
    {
    result.Add(column.Value);
    }
    }
    dg.ItemsSource = result;
    }
    }

    Parameters details:-
    DataGrid dg, XDocument xDoc, string DescendantsName

    My XDocument looks like this that I am trying to pass as parameter :-

    0
    9835496788
    Active

    DescendentsName is “ResponseData”.

    I am trying to bind datagrid dynamically where IsB2B, MdnId & WalletStatus will be Columns of Datagrid and 0, 9835496788 & Active will be a single row (each value corresponding to it’s Column ) of the DataGrid.

    My output is like this;-

    But I want like this:-

    Anup Kumar
    Delhi,India.

  5. Do you mind if I quote a couple of your articles as
    long as I provide credit and sources back to your website?
    My blog site is in the exact same area of interest
    as yours and my visitors would really benefit from some of the information you present here.
    Please let me know if this alright with you.
    Thanks!

Leave a comment