how to add image dynamically to datagrid columns
-
Tuesday, July 27, 2010 10:03 AM
Hello,
I have datagrid in which i have to display image conditionally , suppose in my grid i have one column of percentage then i have to add green signal image for percentage above 80 and yellow signal for below 50 indicating pass and red signal for failed students how is this possible?
i get data from sharepoint service.
i do not have fixed columns , i bind columns dynamically in code behind plz help me urgently.
thanks
All Replies
-
Tuesday, July 27, 2010 10:29 AM
You can use an image converter to achieve this. Here's an example of setting up a template column to use an image converter from code behind.
Dim tc As New DataGridTemplateColumn tc.Header = "Your Header" Dim sb As New StringBuilder sb.Append("<DataTemplate ") sb.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ") sb.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ") sb.Append("xmlns:local = 'clr-namespace:YourNamespace;assembly=YourAssembly'>") sb.Append("<Grid>") sb.Append("<Grid.Resources>") sb.Append("local:ImageConverter x:Key='ImageConverter' />") sb.Append("</Grid.Resources>") sb.Append("<TextBlock ") sb.Append("Text = '{Binding YourField, ") sb.Append("Converter={StaticResource ImageConverter}}' ") sb.Append("</Grid>") sb.Append("</DataTemplate>") tc.CellTemplate = XamlReader.Load(sb.ToString()) YourDataGrid.Columns.Add(tc)
-
Tuesday, July 27, 2010 10:42 AM
i do not have fixed columns , i bind columns dynamically in code behind plz help me urgently.
Define a DataGridCellTemplate in XAML and put a Image control in the Cell. Set the Binding on the Source property:
<DataTemplate x:Key="ImageColTemplate">
<Image Source="{Binding Converter="{StaticResource ImageConverter}" />
</DataTemplate>
Write your ImageConverter so it returns correct image URL based on the Data on that row.
In your code, create a DataTemplateColumn,
DataGridTemplateColumn col = new DataGridTemplateColumn();
col.CellTemplate = this.Resources["ImageColTemplate"] as DataTemplate;theDataGrid.Columns.Add(col);
-
Wednesday, July 28, 2010 8:19 AM
this is good idea i at least found some solution for my problem

where should i write <DataTemplate> part in XAML , i am little bit new to silverlight so i do not know the exact position
can you give me some sample for Converter class with this type of condition, my images are stored in project only.
Thanks a lot
-
Wednesday, July 28, 2010 8:23 AM
thanks for reply . it is good idea
-
Wednesday, July 28, 2010 11:01 AM
where should i write <DataTemplate> part in XAML
If you want to define it in XAML, you can put it in your UserControl's Resources area:
<UserControl ...
>
<UserControl.Resources>
<DataTemplate x:Key="yourKey" ... />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
....
</Grid>
</UserControl>
Or under your DataGrid.Resources:
<dg:DataGrid x:Name="DG" ...>
<dg:DataGrid.Resources>
<DataTemplate x:Key="yourKey" ... />
</dg:DataGrid.Resources>
...
</dg:DataGrid>
Depending on where you put it, in code, you need to refer it in code like this:
DataTemplate dt = this.Resources["YourKey"] as DataTemplate; //If you put it under UserControl.Resources
or
DataTemplate dt = DG.Resources["YourKey"] as DataTemplate; //If you put it under DataGrid.Resources
-
Wednesday, July 28, 2010 11:19 AM
can you give me some sample for Converter class with this type of condition, my images are stored in project only.
See this thread:
http://betaforums.silverlight.net/forums/p/187291/429215.aspx
-
Thursday, July 29, 2010 5:33 AM
public class UrlConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string format = parameter as string;YourDataObject data = value;
string queryParm = "id=" + data.ID + "&status=" + data.Status ...; // Build your query string here use the DataObject passed in as Value
if (!string.IsNullOrEmpty(format))
return string.Format(culture, format, queryParm);
else
return value.ToString();
}public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}so this is the code ok but i have not understood what is parameter, targettype,value
what is YourDataObject in my case , is it string or something else?
and above how should i give URL condition in this code? so as to return correct url of my image.
-
Thursday, July 29, 2010 10:25 AM
The value you'll be passing in is the grade that needs to have an image associated with it.
Public Class ImageConverter Implements IValueConverter Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object _ Implements System.Windows.Data.IValueConverter.Convert Select Case CInt(value) Case Is > 80 Return New BitmapImage(New Uri("../Images/Green.png", UriKind.Relative)) Case Is > 50 Return New BitmapImage(New Uri("../Images/Yellow.png", UriKind.Relative)) Case Else Return New BitmapImage(New Uri("../Images/Red.png", UriKind.Relative)) End Select End Function Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack Throw New NotImplementedException End Function End Class
Here's how I set up my template column. It doesn't matter if you do it like this or from XAML like sladapter suggested.Dim Grades As New List(Of Integer)(New Integer() {90, 50, 70, 95, 85, 30}) Dim sp As New StackPanel sp.Orientation = Orientation.Vertical LayoutRoot.Children.Add(sp) Dim dg As New DataGrid dg.ItemsSource = Grades dg.AutoGenerateColumns = False sp.Children.Add(dg) Dim dt = (<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:my='clr-namespace:TestRC2;assembly=TestRC2'> <Grid> <Grid.Resources> <my:ImageConverter x:Key='ImageConverter'/> </Grid.Resources> <Image Source='{Binding Converter={StaticResource ImageConverter}}'/> </Grid> </DataTemplate>).ToString() Dim tc As New DataGridTemplateColumn tc.Header = "Image Column" tc.CellTemplate = XamlReader.Load(dt) dg.Columns.Add(tc)
Put a break point in the Select Case statement and you'll see the grade being passed in as the value.
-
Thursday, July 29, 2010 11:48 AM
so this is the code ok but i have not understood what is parameter, targettype,value
what is YourDataObject in my case , is it string or something else?
The value parameter in the Converter is the data you passed in the Binding. Say your data object is something like this:
public class YourData
{
public int Percentage {get;set;}
public string Name {get; set;}
...
}
You set the binding like this by specifying a Path:
<Image Source="{Binding Percentage, Converter="{StaticResource YourUrlConverter}}" .../>
Then the value object should be the Percentage, the code should be like this:
int p = value as int;
if(p > 80)
return GreenImageURL;
else if(p<50)
return YellowImageURL;
else
...
If you set the Binding without providing a path, then the Value object would be the whole DataContext which is YourData object:
<Image Source="{Binding Converter="{StaticResource YourUrlConverter}}" ../>
The code should be like this:
YoudData data= value as YourData;
if(data.Percentage > 80)
return GreenImageURL;
else if(data.Percentage <50)
return YellowImageURL;
else
...
"Parameter" can be useful. You can specify ConverterParameter in the binding, it gives you extra control on how to do the conversion. Using it to provide Format string is a good example.
-
Thursday, July 29, 2010 4:33 PM
sladapter is correct that I was binding to the DataContext of the DataGrid which in my previous example was simply a list of Integer.
Here's a more complete example using a Student class. It implements INotifyProperty changes which the ObservableCollection can take advantage of so when you change the Student's score in the numeric column the image changes to reflect the new score.
The ImageConverter is the same one I used in my previous post.
Public Class Student Implements INotifyPropertyChanged Public Sub New(ByVal name As String, ByVal score As Integer) _name = name _score = score End Sub Private Property _name As String Public Property name As String Get Return _name End Get Set(ByVal value As String) _name = value RaisePropertyChanged("name") End Set End Property Private Property _score As Integer Public Property score As Integer Get Return _score End Get Set(ByVal value As Integer) _score = value RaisePropertyChanged("score") End Set End Property Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) _ Implements INotifyPropertyChanged.PropertyChanged Sub RaisePropertyChanged(ByVal propertyName As String) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub End ClassDim Students As New ObservableCollection(Of Student) From { New Student("Joe", 90), New Student("Mary", 50), New Student("Billy", 70), New Student("Shelly", 95), New Student("Johnny", 85), New Student("Tim", 30) } Dim sp As New StackPanel sp.Orientation = Orientation.Vertical LayoutRoot.Children.Add(sp) Dim dg As New DataGrid dg.ItemsSource = Students dg.AutoGenerateColumns = False sp.Children.Add(dg) Dim namesColumn As New DataGridTextColumn namesColumn.Header = "Text Column" namesColumn.Binding = New Data.Binding With { .Path = New PropertyPath("name") } dg.Columns.Add(namesColumn) Dim scoresImageTemplate = (<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:my='clr-namespace:TestRC2;assembly=TestRC2'> <Grid Width='50' Height='50'> <Grid.Resources> <my:ImageConverter x:Key='ImageConverter'/> </Grid.Resources> <Image Source='{Binding score, Converter={StaticResource ImageConverter}}'/> </Grid> </DataTemplate>).ToString() Dim scoresImageTemplateColumn As New DataGridTemplateColumn scoresImageTemplateColumn.Header = "Image Column" scoresImageTemplateColumn.CellTemplate = XamlReader.Load(scoresImageTemplate) dg.Columns.Add(scoresImageTemplateColumn) Dim scoresNumericColumn As New DataGridTextColumn scoresNumericColumn.Header = "Scores Text Column" scoresNumericColumn.Binding = New Data.Binding With { .Path = New PropertyPath("score"), .Mode = Data.BindingMode.TwoWay } dg.Columns.Add(scoresNumericColumn)
-
Monday, August 02, 2010 6:40 AM
Hello Matt.P,
I have used the code as you gave but it gives me error called unknown namespace though i have provided my namespace name. everything in code i have coded as per my project.
-
Monday, August 02, 2010 10:57 AM
Where are you getting the namespace error? In the datatemplate for the image column?
Please post the problem section of your code so I can take a look at it.
-
Tuesday, August 03, 2010 5:16 AM
myTemplateColumn.CellTemplate
= (DataTemplate)XamlReader.Load(
"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:my='clr-namespace:DataSetInDataGrid.Silverlight'>" +
"<Grid Width='50' Height='50'>" +
"<Grid.Resources>" +
"<my:UrlConvert x:Key='ImageConverter'/>" +
"</Grid.Resources>" +
"<Image Source='{Binding score, Converter={StaticResource ImageConverter}}'/>" +
"</Grid>" + " </DataTemplate>");I have underlined the line where i get the error , and this is what my code. can you please tell me what is failer ?
-
Tuesday, August 03, 2010 10:10 AM
Ah, you're getting a message that ImageConverter couldn't be found because 'my' is an unknown namespace. Add the assembly information to your declaration and that should go away (Take a look at my previous code for an example).
-
Wednesday, August 04, 2010 5:43 AM
Hi Matt.P and Sladpter,
thanks a lot for your great help, it is working like a magic.
thanks at ton

