I would think that this would be incredibly simple, but I've searched all over and can't seem to find an answer. I have a DataGridTemplateColumn that I want to use to display a value that isn't in the DataContext of the DataGrid. I.e. I have an entity that has different names based on the culture. When the grid loads, I want to go get the appropriate name based on the current culture. Every time I see anything about DataGridTemplateColumns, they're always using the Binding syntax. I can't do that here. What C# code do I need to access the "nameValue" TextBlock in the following XAML, and in what event handler should I access it:
<Datagrid:DataGridTemplateColumn Header="Name" x:Name="nameField">
<Datagrid:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="nameValue" />
</StackPanel>
</DataTemplate>
</Datagrid:DataGridTemplateColumn.CellTemplate>
</Datagrid:DataGridTemplateColumn>
Thanks to all in advance and I'm sorry for the super n00b question.
You can still use the binding syntax, it sounds like you just need to bind to a static method instead of the data context of the grid. There is a good reference here http://blog.mrlacey.co.uk/2011/03/binding-to-static-classes-in-windows.html Taking that as an example and modifying for your case.
First: Setup your grid as you would normally, item source and columns, standard data binding. This will take care of any columns you need from the database or other source.
Second: In your project add your static class
namespace StaticBinding
{
public class MyStaticClass
{
private static string myStaticProperty;
public static string MyStaticProperty
{
get
{ return
(CultureInfo.CurrentCulture.Name == "en-US" ? "US" : "Other");
}
set { myStaticProperty = value; } }
}
}
Third: Add your new resource to app resources
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SampleData="clr-namespace:Expression.Blend.SampleData.SampleDataSource" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="SilverlightApplication28.App"
xmlns:myns="clr-namespace:StaticBinding"
>
<Application.Resources>
<myns:MyStaticClass x:Name="MyStaticClass"></myns:MyStaticClass>
</Application.Resources>
Finally: Set the binding in your TextBlock, if you've built your project, you should be able to see the property in the binding editor window.
<sdk:DataGrid AutoGenerateColumns="False" Height="171" HorizontalAlignment="Left" Margin="61,53,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="263" ItemsSource="{Binding Collection}" LoadingRow="dataGrid1_LoadingRow" Loaded="dataGrid1_Loaded" >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Property1}" Header="Property1"/>
<sdk:DataGridCheckBoxColumn Binding="{Binding Property2}" Header="Property2"/>
<sdk:DataGridTextColumn Binding="{Binding Property3}" Header="Property3"/>
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="nameValue" Text="{Binding Source={StaticResource MyStaticClass}, Path=MyStaticProperty}" />
</StackPanel>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
Related
So maybe I am approaching this the wrong way, feel free to give any advice or tips.
Currently working with a DataGrid table in wpf using powershell to do all the logic. Here is the table:
What is the best way to properly extract all the data INCLUDING the combobox selected value from a selected row?
Currently I am trying this:
$test = $AddServerwpf.ServerGrid.SelectedItems[0]
Write-Host "Selected: $test"
For context $AddServerwpf contains all the objects for that window. ServerGrid is the DataGrid object. I am using .SelectedItems[0] to get that row.
This returns:
Selected: #{Server=server1; Environment=Prod; ServiceAccount=System.Object[]}
If I go one step further with:
$AddServerwpf.ServerGrid.SelectedItems[0].ServiceAccount
I get:
Selected: account1 account2 account3
This obviously doesn't tell me which account was selected from the drop down. How can I get the combobox selection? I have looked pretty deeply through google with other questions about this and I have not found a working answer. How do I properly bind the combobox to the datagrid? Or is it better to get to the Combobox object somehow and extract the text?
Here is the XAML:
<Window x:Class="ServerManagmentApp.AddServer" x:Name="AddServerWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ServerManagmentApp"
mc:Ignorable="d"
Title="AddServer" Height="359.7" Width="387.4" Background="#FF2B2929">
<Grid>
<Button x:Name="AddServerButton" Content="Add Server" HorizontalAlignment="Left" Margin="220,260,0,0" VerticalAlignment="Top" Width="120" Height="40" Background="#FF1FD14F"/>
<DataGrid x:Name="ServerGrid" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="213" Width="275" Background="#FF888F8A" SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Server" Binding="{Binding Server}" Width="*" />
<DataGridTextColumn Header="Environment" Binding="{Binding Environment}" Width="*" />
<DataGridTemplateColumn Header="ServiceAccount" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="ServiceAccount" ItemsSource="{Binding ServiceAccount}" SelectedIndex="0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Spent a couple hours trying to get past this roadblock and any help would be appreciated. I am new to this and trying to wrap my head around how this binding works while using powershell.
EDIT:
Here is how I am populating the DataGrid if that helps
$list = "account1","account2","account3"
$AddServerwpf.ServerGrid.AddChild([pscustomobject{Server='server1';Environment='Prod';ServiceAccount=$list})
$AddServerwpf.ServerGrid.AddChild([pscustomobject]#{Server='server2';Environment='Prod';ServiceAccount=$list})
$AddServerwpf.ServerGrid.AddChild([pscustomobject]#{Server='server3';Environment='Prod';ServiceAccount=$list})
You should bind the SelectedItem property of the ComboBox to a property of your data object where the Server, Environment and ServiceAccount properties are already defined:
<ComboBox x:Name="ServiceAccount" ItemsSource="{Binding ServiceAccount}"
SelectedItem={Binding SelectedAccount, UpdateSourceTrigger=PropertyChanged}" />
$list = "account1","account2","account3"
$AddServerwpf.ServerGrid.AddChild([pscustomobject{Server='server1';Environment='Prod';ServiceAccount=$list;SelectedAccount='account1'})
$AddServerwpf.ServerGrid.AddChild([pscustomobject]#{Server='server2';Environment='Prod';ServiceAccount=$list;SelectedAccount='account1'})
$AddServerwpf.ServerGrid.AddChild([pscustomobject]#{Server='server3';Environment='Prod';ServiceAccount=$list;SelectedAccount='account1'})
You can then get the selected value of an item using this property, e.g.:
$AddServerwpf.ServerGrid.SelectedItems[0].SelectedAccount
Solved problem, but still have questions. See end of post, or read on for context.
I'm trying to setup a WPF datagrid which has many templated columns with comboboxes inside of them. In particular I'm having trouble with data-binding.
Data Model
First, I have Entry, which contains 4 properties:
Name
Customer
Color
Type
The most interesting property is Color which has two more sub properties:
ColorString
Index
Goal
I need to create a data grid where each row corresponds to an Entry object. The Customer, Color, and Type properties all have comboboxes that allow for a selection of dynamically populated choices. I need the selected item for each combobox to bind to the entry's respective property.
Screenshot
Questions:
How do I properly set the data contexts for the data grid and for each combobox?
For the data grid, I'm setting the data context programmatically to an instance of ObservableCollection.
private ObservableCollection<Entry> entries = new ObservableCollection<Entry>();
public MainWindow()
{
InitializeComponent();
entries.Add(new Entry("Foo", "Customer1", new MyColor("#00000000", 1), "Type1"));
entries.Add(new Entry("Bar", "Customer2", new MyColor("#00000000", 1), "Type2"));
LayerMapGrid.DataContext = entries; //Set data-context of datagrid
}
For the color combobox, I'm using an ObjectDataProvider in my XAML:
<Window.Resources>
<ObjectDataProvider x:Key="Colors" ObjectType="{x:Type local:MyColor}" MethodName="GetColors"/>
</Window.Resources>
This is how I bind the ObjectDataProvider
<ComboBox ItemsSource="{Binding Source={StaticResource Colors}}"/>
In the MyColor class, I've created the method below:
public static ObservableCollection<MyColor> GetColors()
{
ObservableCollection<MyColor> colors = new ObservableCollection<MyColor>();
//... Fill collection... (omitted for brevity)
return colors;
}
The good news is that ALL of the above code WORKS. However is it a good approach to the problem at hand?
This my next and more important question:
How do I bind the selected items of the comboboxes so that ObservableCollection<Entry> is updated?
I'm aware that I need to set the UpdateSourceTrigger="PropertyChanged", so that my source, which is the Entry collection is updated.
Here is my current XAML code for setting up my entire data grid. Note: I haven't implemented the customer and type comboboxes yet. I'm really just concerned with the color combobox:
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" Name="LayerMapGrid">
<DataGrid.Columns>
<!--Name Column-->
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Control.HorizontalContentAlignment" Value="Center" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
</DataGridTemplateColumn>
<!--Customer Column-->
<DataGridTemplateColumn Header="Customer">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding CustomerName, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--Color Column-->
<DataGridTemplateColumn Header="Color">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource Colors}}" SelectedItem="{Binding Color, ElementName=LayerMapGrid, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<DockPanel Margin="2">
<Border DockPanel.Dock="Left" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="Black" Margin="1" Width="10" Height="10">
<Rectangle Name="ColorRec" Fill="{Binding ColorString}"/>
</Border>
<TextBlock Padding="4,2,2,2" Text="{Binding ColorString}" VerticalAlignment="Center"/>
</DockPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--Type Column-->
<DataGridTemplateColumn Header="Type">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding Type, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Your assistance is greatly appreciated. I've been banging my head on the wall for about 16 hours with this.
-Nick Miller
EDIT:
I found the solution (and as always immediately after requesting help), but I don't understand how it works.
In the XAML, I've changed the combobox binding to be the following:
<ComboBox ItemsSource="{Binding Source={StaticResource Colors}}" SelectedItem="{Binding Color, UpdateSourceTrigger=PropertyChanged}">
What exactly is happening here?
Why is the combobox now referring to the datagrid's data context? Doesn't that get overriden when I set the ItemsSource to point to my ObjectDataProvider?
How do I properly set the data contexts for the data grid and for each combobox?
You don't. Normally in WPF, we set the DataContext property on the UserControl, or Window that we are designing, not on individual controls. In this way, all the controls in the view have access to the data properties.
How do I bind the selected items of the comboboxes so that ObservableCollection is updated?
Again, you don't do what you are doing. Rather than using an ObjectDataProvider, you should just have a property of type ObservableCollection<MyColor> in the code behind and bind to that directly. And you should be binding a public Entries property to the DataGrid.ItemsSource property, not setting the private entries field as the DataContext. You really need to read through the Data Binding Overview page on MSDN for further help with this.
Set the DataContext of MainWindow.xaml to itself (which generally is a not a good idea):
public MainWindow()
{
InitializeComponent();
Entries.Add(new Entry("Foo", "Customer1", new MyColor("#00000000", 1), "Type1"));
Entries.Add(new Entry("Bar", "Customer2", new MyColor("#00000000", 1), "Type2"));
DataContext = this; //Set DataContext to itself so you can access properties here
}
Then in MainWindow.xaml:
<DataGrid ItemsSource="{Binding Entries}" ... />
The DataTemplates in each row of the DataGrid automatically have the relevant item in the data bound collection set as the DataContext, so you automatically get access to the properties from the relevant class. Again... no need to set any DataContexts manually. If you have further questions, please read the linked article, because the answers are there.
UPDATE >>>
Let's be clear about something... I am not your personal mentor, so this will be my last reply.
How do I overcome the combobox inheriting the data context of the data grid?
To data bind to the object that is set as the Window.DataContext, you just need to use a valid Binding Path and some basic logic:
<ComboBox ItemsSource="{Binding DataContext.MyColors, RelativeSource={RelativeSource
AncestorType={x:Type YourLocalPrefix:MainWindow}}}" />
Silverlight 5 question. I can group items in a DataGrid by using PagedCollectionView as its ItemsSource (via GroupDescriptions.Add). No problem. However, we are designers (not experienced programmers) working on a prototype and are using the Blend “Data” window extensively where we can conveniently create sample data sources / collections and sample enter data. Unfortunately, GroupDescriptions.Add doesn’t seem to work on these xml-based collections created through the “Data” window.
Is there a way to use grouping in DataGrid without having to use C#? Or is there a way to group the sample data created through the “Data” window in a DataGrid?
I did my research and I'm starting to think this may not be possible. My first post, go easy on me! Thanks -
How to view Silverlight Datagrid group in designer (blend or VS) :
You can try to create a XAML CollectionViewSource bind to a sample data Collection :
Create a new sample data named "customerSampleData" ;
Add a collection property (named "Collection") with 2 sub properties (Name, Age) ;
Add the CollectionViewSource in resources with PropertyGroupDescription.
See the last step :
xmlns:compMod="clr-namespace:System.ComponentModel;assembly=System.Windows"
xmlns:SampleData="clr-namespace:Expression.Blend.SampleData.customerSampleData"
...
</UserControl.Resources>
<SampleData:customerSampleData x:Key="customerSampleData" d:IsDataSource="True"/>
<CollectionViewSource
x:Key="dataSource"
d:IsDataSource="True"
Source="{Binding Collection, Source={StaticResource customerSampleData}}">
<CollectionViewSource.SortDescriptions>
<compMod:SortDescription PropertyName="Name" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Age"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" DataContext="">
<sdk:DataGrid AutoGenerateColumns="False" DataContext="{Binding Source={StaticResource dataSource}}" ItemsSource="{Binding}" >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
<sdk:DataGridTextColumn Binding="{Binding Age}" Header="Age"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
I'd like to access a Object from my UserControl from within the Datgrids ColumnTemplate.
This doesn't work. Now I've read it's because of the Datacontext.
I found this Example, which should fix this: http://blog.errorok.com/2010/09/09/212/
But the Event: ColumnDataContextChanged is never called in my Project!
here's a part of my XAML:
<DataGridTemplateColumn Header="Database-Fieldtype" Width="Auto" IsReadOnly="False" SortMemberPath="DatabaseFieldType">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DatabaseFieldType}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ConfigurationTool:EditProtocolDatasets}}, Path=grdDatasets.SelectedItem.Storage.DatabaseFieldTypes}"
SelectedItem="{Binding DatabaseFieldType}"
VerticalAlignment="Top" Width="179" Padding="0" Margin="0">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
ConfigurationTool:EditProtocolDatasets is my UserControl, grdDatasets is another Datagrid, to which SelectedItem I'd like to bind!
Okay, I'm going to suggest a completely different direction than my first one. My guess is that you have the ItemsSource for grdDatasets bound to something.
For the item that's going to act as your datacontext for the control, make sure it has the following characteristics, or at least a comparable structure:
public class ListOfDataSets : DependencyObject
{
public IEnumerable<DataSetOption> Items
{
get
{
...Whatever you normally use to get your DataSetOptions...
}
}
public DataSetOption SelectedItem
{
get { return (DataSetOption)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(DataSetOption), typeof(ListOfDataSets), new PropertyMetadata(null));
}
The key here is that you have one property that is a list of your choices, and another property that represents one of those items.
Then, in your XAML, your control can have the following structure:
<UserControl>
<UserControl.Resources>
<ConfigurationTool:ListOfDatasets x:Key=DataSetOptions />
</UserControl.Resources>
<StackPanel Name="LayoutRoot">
<DataGrid Name="grdDatasets"
ItemsSource="{Binding Source={StaticResource DataSetOptions}, Path=Items}"
SelectedItem="{Binding Source={StaticResource DataSetOptions}, Path=SelectedItem}"
...
</DataGrid>
...
<DataGrid Name="OtherDataGrid" ItemsSource="{Binding OtherSource}">
<DataGrid.Columns>
...
<DataGridTemplateColumn Header="Database-Fieldtype" Width="Auto" IsReadOnly="False" SortMemberPath="DatabaseFieldType">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DatabaseFieldType}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{StaticResource DataSetOptions}, Path=SelectedItem.Storage.DatabaseFieldTypes}" SelectedItem="{Binding DatabaseFieldType, Mode=TwoWay}"
VerticalAlignment="Top" Width="179" Padding="0" Margin="0">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</Datagrid.Columns>
</DataGrid>
</StackPanel>
</UserControl>
I actually tried this structure out, and the databinding works fine. If the DataSetOptions change a lot, though, this solution may not work, unless you're using MVVM, and the ViewModel is good at tracking what options are available, and presents them properly to the View.
Hopefully this makes sense. I actually tried this one before answering.
I was not correct with my original answer, and overestimated the capabilities of RelativeSource before I experimented with it.
---Original text below---
I think I can help, but I need a few more details. For now I'm just going to work off assumptions.
Assumption 1: You're in a WPF UserControl with a DataGrid that has a defined ItemsSource.
Assumption 2: The UserControl has another element that you want a column within your DataGrid to have access to.
If these two assumptions are correct, it is a much better problem to have in WPF than in Silverlight.
Each row in your DataGrid is going to be working from within a DataContext that consists of the Item for that row. But, you can reach outside of the cell's (or any) DataContext with a RelativeSource.
So, if you wanted to go up the Visual Tree to get to your control's Width, you would use:
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MyUserControl}}, Path=Width}
This will trace upward in the Visual Tree until an object of type "MyUserControl" is found, at which point it will grab the "Width" property and bind to it.
The Path doesn't have to be only one item deep, either. You can run up an down your visual tree as required. As this gets more complex, though, your code is going to be more fragile.
If this isn't correct, please post your XAML (or something similar) and say so, and I'll spin up a test environment and edit my post.
I have a combobox defined as follows:
<ComboBox x:Name="cboDept" Grid.Row="0" Margin="8,8,8,8" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"
ItemsSource="{Binding Source={StaticResource cvsCategories}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Width="Auto" Height="Auto">
<sdk:Label Content="{Binding CategoryID}" Height="20" />
<sdk:Label Content="{Binding CategoryName}" Height="20" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
It works fine. However, once I select an item in the list, I want a different template to be applied to the combobox selected item being shown to the user (the item shown after the disappearance of popup). In the above case, I want only CategoryName to be displayed in the ComboBox once I select the respective item.
Can anyone let me know on how to achieve this?
thanks
What you need to do is create a ResourceDictionary containing a few defined templates yourself. In the below, ComboBoxTemplateOne and ComboBoxTeplateTwo are user controls that are set out to display the combobox in the manor you want.
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="TemplateOne">
<local:ComboBoxTemplateOne />
</DataTemplate>
<DataTemplate x:Key="TemplateTwo">
<local:ComboBoxTemplateTwo />
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
You will then need to create your own class that inherits from ContentControl "DataTemplateSelector", overriding OnContentChanged
Protected Overrides Sub OnContentChanged(ByVal oldContent As Object, ByVal newContent As Object)
MyBase.OnContentChanged(oldContent, newContent)
Me.ContentTemplate = SelectTemplate(newContent, Me)
End Sub
You will then need to create another class that inherits from the above DataTemplateSelector which overrides SelectTemplate ("TemplateSelectorClass"), which will return the DataTemplate defined above ("TemplateOne" or "TemplateTwo").
Also in this derived class, you will need to define a property for each of the templates you have
Public Property ComboboxTemplateOne As DataTemplate
Then head back to your XAML and n the blow XAML
<local:TemplateSelectorClass ComboboxTemplateOne="{StaticResource TemplateOne}" Content="{Binding Path=ActiveWorkspace}>
This should work, as it is effectively doing the same work as setting the "DataTemplate" property in WPF (which doesn't exist in SilverLight)
I realise there are a fair few steps here and its quite fiddly, but hopefully this will get you there. Any questions just shout.