I am building a DataGrid with DataGridTemplateColumns. The CellTemplate is created as DataTemplate in XAML:
<DataTemplate x:Key="StringCell">
<Grid DataContext="{Binding Path=Cells.Values[3]}">
<TextBlock Text="{Binding Path=AttributeValue.ObjectValue, Mode=OneWay}"
TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
This is actually working, but I want to set the DataContext of the Grid in code when creating the Column. I tried this:
DataTemplate dt = cellTemplates["StringCell"] as DataTemplate;
(dt.LoadContent() as Grid).SetBinding(DataContextProperty, new Binding("Cells.Values[3]") { Mode = BindingMode.OneWay });
DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn()
{
CellTemplate = dt
};
but it's not working because LoadContent creates a new instance and doesn't change the template. Is there a way to set the DataContext in code?
CodePudding user response:
Rather than modifying an existing template (which is not always possible), it's easier to create a new one from a string.
You didn't show the implementation of the classes used, so I'll show an example for such a class structure:
namespace Core2022.SO.ottoKranz
{
public class SomeClass
{
public SomeItem[]? Cells { get; set; }
}
public class SomeItem
{
public AttributeClass? AttributeValue { get; set; }
}
public class AttributeClass
{
public object? ObjectValue { get; set; }
}
}
And here is an example of creating a data template:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
namespace Core2022.SO.ottoKranz
{
public class CodeBehind
{
const string DataTemplateString = @"
<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:local='clr-namespace:Core2022.SO.ottoKranz'
DataType='local:SomeClass'>
<Grid DataContext='{{Binding Path=Cells.Values[{0}]}}'>
<TextBlock Text='{{Binding Path=AttributeValue.ObjectValue, Mode=OneWay}}'
TextWrapping='Wrap'/>
</Grid>
</DataTemplate>";
public static void OnGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
int index = 3;
string templateString =string.Format(DataTemplateString, index);
DataTemplate template = (DataTemplate) XamlReader.Parse(templateString);
DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn()
{
CellTemplate = template
};
e.Column = dataGridTemplateColumn;
}
}
}
CodePudding user response:
I found a solution in this thread:
private DataTemplate GeneratePropertyBoundTemplate(int i, string templateKey)
{
DataTemplate cellTemplate = cellTemplates[templateKey] as DataTemplate; //Load DataTemplate from Resource
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(ContentPresenter));
factory.SetValue(ContentPresenter.ContentTemplateProperty, cellTemplate);
factory.SetBinding(ContentPresenter.ContentProperty, new Binding("Cells.Values[" i "]"));
return new DataTemplate { VisualTree = factory };
}
You just wrap the DataTemplate in a ContentPresenter and set his Binding.