Home > Enterprise >  Set Binding of Element inside Datatemplate
Set Binding of Element inside Datatemplate

Time:10-27

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.

  • Related