DataGrid cell template

May 14, 2009 at 2:46 PM
Edited May 14, 2009 at 3:03 PM

Hi all,

I'm in the situation where I had to set up my data grid dynamically in the code behind. The problem that I have is that I can't make the cell template to work. I've read that there have been some problems with setting the cell style on the all grid, is that solved in the latest release?

Here is what I have:

Objects

{

string DisplayValue

. . .

}

ObservableColection<Objects> dataSource;

DataGrid.ItemsSource=dataSource;

If I set the binding path for columns like this path = new Binding("Objects[" + index + "].DisplayValue");

then that's fine. But I want to use a cell template so that the binding will look like this

path = new Binding("Objects[" + index + "]");

and then use the other properties that Objects have. This is what I used in the XAML for the new path:

<Style x:Key="CellStyle" TargetType="{x:Type dg:DataGridCell}">

<Setter Property="Template">

<Setter.Value>Setter.Value>

<ControlTemplate TargetType="{x:Type dg:DataGridCell}"> 

<TextBlock Text="{Binding Path=DispplayValue}"/>

<ControlTemplate>  

</

 

</Setter>  

</Style>

 

but this does not seem to work. How can I make cell template that will work for my case?

Thanks for any suggestion,

John.  

May 19, 2009 at 12:09 PM
Edited May 19, 2009 at 12:10 PM

Can anybody help me ?

Coordinator
May 19, 2009 at 8:36 PM

Your DataGrid column, let's assume it's a DataGridTextColumn, should have a Binding property set to {Binding Path=DisplayValue}. Then, you don't need to specify any template.

If you are using a DataGridTemplateColumn, then in your template, your TextBlock will have Text="{Binding Path=DisplayValue}".

There should be no need to use index in any of the bindings since that should be taken care of when each row is generated.

Ben

May 20, 2009 at 8:38 AM

Thank you for your replay Ben,

You are absolutely right on this, because I printed the wrong code sample and I feel ashamed for that. Please, let me rectify it:

  

Object

{

string DisplayValue

int Id;

. . .

}

Dictionary<int, Object> objectsMap;

ObservableColection<objectsMap> dataSource;

DataGrid.ItemsSource=dataSource;

My columns are DataGridTextColumn and they have the binding path set like this {Binding Path=objectsMap[Id].DisplayValue}

but I need to have {Binding Path=objectsMap[Id]}

so that each cell to be a Object element I tried this style for cell when I set this path {Binding Path=objectsMap[Id]}:

<Style x:Key="CellStyle" TargetType="{x:Type dg:DataGridCell}">

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="{x:Type dg:DataGridCell}"> 

<TextBlock Text="{Binding Path=DisplayValue}"/>

<ControlTemplate>  

</Setter.Value>

</Setter>  

</Style>

which dos not seem to work. How can I make it work?

Thank you,

John.

Coordinator
May 20, 2009 at 10:42 PM

Your ItemsSource is bound to a list of dictionaries. That means for a particular row, you have a dictionary. Columns allow you to specify a binding to a property on the row data item, a dictionary in this case. So, when you said Path=objectsMap[Id] what you asked for was for the property objectsMap on Dictionary (which doesn't exist) and then the Item property on that object.

Since your dictionary's key is an int and bindings do not support parameterized paths, you'll only be able to access items in the dictionary using explicit integers. So, Id would need to be something like 3.

So, try something like {Binding Path=[3]} or {Binding Path=Item[3]} (not sure if either will actually work).

Ben

May 21, 2009 at 8:36 AM

Hi Ben,

I appreciate your efforts of helping me.

My real problem is not setting the path, the path works if I set the following path {Binding Path=objectsMap[Id].DisplayValue} because I set that programaticly in the code behaind. My problem is templating the cell so that I can set the path to an object in objectsMap dictionary like this {Binding Path=objectsMap[Id]}, where Id is an index(1,2,3..). In this case I will have a Object in each cell and from there, in the cell template I will like to use Object properties to set what to display and how the cell will look.

But so far all cell templates that I used are not displaying anything, maybe because I set the cell template in the cell style. And that's because I want to have a global cell template for the complete grid and not for individual columns, like in DataGridTemplateColumn where you can set the cell template for the cells in that column.

I hope that this will make sense to you. 

May 21, 2009 at 3:38 PM
Edited May 21, 2009 at 3:59 PM

From what I've read here there is not a straightforward solution to my problem:

DataTextColumns allow me to set the path the way I need

DataGridTemplateColumns allow me to set the cell template but I can not set the binding that I need in the way I need, which is binding display value and then other properties that set my display style.

The solution that I come to is this:

Having a column class that extends the DataTextColumns by setting the binding to the properties that define my style

 

public class MyDataGridBoundColumn : DataGridTextColumn

{

 

static MyDataGridBoundColumn()

{

}

 

private BindingBase _propertyBinding   ;

 

public BindingBase PropertyBinding

{ 

get { return _propertyBinding; }

set { _propertyBinding = value; }

protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)

{ 

TextBlock textBlock = (TextBlock)base.GenerateElement(cell, dataItem); BindingOperations.SetBinding(textBlock, Property, PropertyBinding); return textBlock;  

}

}

I hope this will help others with the same problem or similar problems.