Problems binding to a the content of a WPF DataGridCell in XAML

扶醉桌前 提交于 2019-12-01 01:12:45

So I found the solution was to do some work in the code behind.

In the AutoGeneratingColumn event create a DataTemplate with a content control and a custom template selector (I create the selector in Xaml and found it as a resource).

Create a binding for the ContentProperty of the ContentControl with e.PropertyName as the path

Create a new DataGridTemplateColumn and set the new columns CellTemplate to your new DataTemplate

replace e.Column with your new column and hey presto the cells datacontext bind with the dynamic property for that column.

If anyone has any refinement to this please feel free to share your thoughts.

Thanks

EDIT: As requested some sample code for my solution

Custom template selector:

public class CustomDataTemplateSelector : DataTemplateSelector
{
    public List<DataTemplate> Templates { get; set; }

    public CustomDataTemplateSelector()
        : base()
    {
        this.Templates = new List<DataTemplate>();
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        DataTemplate template = null;
        if (item != null)
        {
            template = this.Templates.FirstOrDefault(t => t.DataType is Type ? (t.DataType as Type) == item.GetType() : t.DataType.ToString() == item.GetType().ToString());
        }

        if (template == null)
        {
            template = base.SelectTemplate(item, container);
        }

        return template;
    }
}

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="ParentControl">
        <Grid.Resources>
            <local:CustomDataTemplateSelector x:Key="MyTemplateSelector" >
                <local:CustomDataTemplateSelector.Templates>
                    <DataTemplate DataType="{x:Type local:MyCellObject}" >
                        <TextBox Text="{Binding MyStringValue}" IsReadOnly="{Binding IsReadOnly}" />
                    </DataTemplate>
                </local:CustomDataTemplateSelector.Templates>
            </local:CustomDataTemplateSelector>
        </Grid.Resources>
        <DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" >
        </DataGrid>
    </Grid>
</Window>

Code behind:

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    // Get template selector
    CustomDataTemplateSelector selector = ParentControl.FindResource("MyTemplateSelector") as CustomDataTemplateSelector;

    // Create wrapping content control
    FrameworkElementFactory view = new FrameworkElementFactory(typeof(ContentControl));

    // set template selector
    view.SetValue(ContentControl.ContentTemplateSelectorProperty, selector);

    // bind to the property name
    view.SetBinding(ContentControl.ContentProperty, new Binding(e.PropertyName));

    // create the datatemplate
    DataTemplate template = new DataTemplate { VisualTree = view };

    // create the new column
    DataGridTemplateColumn newColumn = new DataGridTemplateColumn { CellTemplate = template };

    // set the columns and hey presto we have bound data
    e.Column = newColumn;
}

There may be a better way to create the data template, I have read recently that Microsoft suggest using a XamlReader but this is how I did it back then. Also I haven't tested this on a dynamic class but I'm sure it should work either way.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!