The question:
Is there a way to define a DataTemplate
in XAML and instantiate it in code (rather than retrieve singleton by FindResource
) and modify its VisualTree
before sending to where a DataTemplate
is required such as DataGridTemplateColumn.CellTemplate
?
Background:
I am displaying a 2-dimensional array data[][]
in a DataGrid
by adding DataGridTemplateColumn
columns on my own and there is a DataTemplate
defined in XAML that knows how to present each element in the array. However the default DataContext
for each cell is the row, i.e. data[x]
. So I need to "parameterize" the DataTemplate
for each column by setting the root visual element's DataContext
to binding "[y]"
where y
is the column index. Currently the DataTemplate
is defined as in DataGrid.Resources
and retrieved by FindResource()
which is returning the same instance every time. Besides calling LoadContent()
gives me the UIElement
tree rather than loading the VisualTree
on the DataTemplate
itself. I am looking for a way to instantiate the DataTemplate
in code, do the desired modification and set to DataGridTemplateColumn.CellTemplate
.
Inspired by Sisyphe's answer, I found this more portable solution:
public class DataGridBoundTemplateColumn : DataGridTemplateColumn
{
public string BindingPath { get; set; }
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
var element = base.GenerateEditingElement(cell, dataItem);
element.SetBinding(ContentPresenter.ContentProperty, new Binding(this.BindingPath));
return element;
}
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
var element = base.GenerateElement(cell, dataItem);
element.SetBinding(ContentPresenter.ContentProperty, new Binding(this.BindingPath));
return element;
}
}
Usage:
var cellTemplate = (DataTemplate)this.dataGrid.FindResource("cellTemplate");
foreach (var c in data.Columns)
{
var col = new DataGridBoundTemplateColumn
{
Header = c.HeaderText,
CellTemplate = cellTemplate,
BindingPath = string.Format("[{0}]", c.Index)
};
this.dataGrid.Columns.Add(col);
}
Hope this helps someone who has the same requirement as the one in my question.
(templateKey as DataTemplate).LoadContent()
Description:
When you call LoadContent
, the UIElement
objects in the DataTemplate
are created, and you can add them to the visual tree of another UIElement
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With