0
votes

I am trying to get a handle on an element within my DataTemplate in code. I am creating a series of DataGridTemplateColumns in code which I then assign to a grid. I want to be able to retrieve the DataTemplate from the xaml, find my element and bind to that particular element.

Here is a short sample code what I am trying to achieve:

<DataTemplate x:Key="dataTemplate">
    <Grid TextBlock.Foreground="LightGreen" Background="Yellow">
        <TextBlock x:Name="txt" />
    </Grid>
</DataTemplate>
DataGridTemplateColumn col = new DataGridTemplateColumn();
col.Header = "Last Name";
Binding b = new Binding("LastName");
DataTemplate dtemplate = (DataTemplate)FindResource("dataTemplate");
TextBlock textBlock = dtemplate.FindName("txt", this);
textBlock.SetBinding(TextBlock.TextProperty, b);
col.CellTemplate = dtemplate;

grid.Columns.Add(col);

Maybe to explain this further: I am trying to create a set of DataGridTemplateColumns on the fly and apply that to a Datagrid. Since I don't know the property to bind to until the time a source gets presented to me I cannot create a DataTemplate that nested within itself has this binding already build in. Like:

<TextBlock Text={Binding=LastName} ... >

So I am forced to create a set of DataGridTemplateColumn in runtime, look for DataTemplate in my resources and THEN try to bind that column to a property (like LastName) on my datasource.

2
DataTemplates are just descriptions, thay don't contain references to objects. But you can change an object which a DataTemplate is applied to.vortexwolf
+1 to previous comment. With the type of code that you're writing here, could you maybe explain the big picture a little more? When I see code directly dealing with UI elements in WPF that's not wrapped in something like a custom Control, it usually sends up a red flag.J Trana
Thanks for the response - I am trying to create a set of DataGridTemplateColumns 'on the fly' rather then being able to specify (and bind them!) them in xaml. This means that I have to be able, after specifying the column, to bind that column to a dp on my data source.Marcel

2 Answers

0
votes

I would approach this via CellStyle instead:

<DataGrid.Resources>
    <Style x:Key="CellStyle" TargetType="{x:Type DataGridCell}">
        <Setter Property="TextBlock.Foreground" Value="LawnGreen"/>
        <Setter Property="Background" Value="Yellow"/>
    </Style>
</DataGrid.Resources>
DataGridTextColumn col = new DataGridTextColumn();
col.Binding = new Binding("Name");
col.CellStyle = dataGrid.Resources["CellStyle"] as Style;
dataGrid.Columns.Add(col);

There are also ways to do this via DataTemplates but it does not seem necessary in this case (unless your problem is more complex).

0
votes

My solution to the problem is something like this:

 GridView viewLayout = new GridView();

        for (int i = 0; i < Apprefs.tables[0].Headers.Count(); i++)
        {
            GridViewColumn gvc = new GridViewColumn();
            string colName = Apprefs.tables[0].Headers[i];
            gvc.Header = colName;
            gvc.Width = 80;
            gvc.CellTemplate = SetTemplete(i); ;
            viewLayout.Columns.Add(gvc);
       }

        listview1.View = viewLayout;

        //set binding
        listview1.ItemsSource = Apprefs.tables[0].Rows;

and then:

    /// <summary>
    /// Create DataTemplate
    /// </summary>
    /// <param name="i"></param>
    /// <returns></returns>
    private DataTemplate SetTemplete(int i)
    {
        DataTemplate template = new DataTemplate();

        //set stack panel 
        FrameworkElementFactory sp = new FrameworkElementFactory(typeof(StackPanel));
        sp.Name = "spBind";
        sp.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

        //set textblock
        FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock));
        sp.Name = "tbBind";
        Binding b = new Binding();
        string ito = "[" + i.ToString() + "]";  // bind by index
        b.Path = new PropertyPath(ito);
        tb.SetBinding(TextBlock.TextProperty, b);
        sp.AppendChild(tb);

        //set the visual tree of the data template 
        template.VisualTree = sp;

        return template;
    }