绑定到XAML中的WPF DataGridCell内容的问题

时间:2012-09-13 15:20:39

标签: wpf xaml datagrid datagridcell

我使用以下帖子来实现绑定到动态对象列表的数据网格

Binding DynamicObject to a DataGrid with automatic column generation?

ITypedList方法GetItemProperties工作正常,显示的网格包含我描述的所有列。

我使用自定义PropertyDescriptor并覆盖上面帖子中描述的GetValue和SetValue方法,我还在动态对象中实现了TryGetMember和TrySetMember方法。

所以基本上我有一个ComplexObject:DynamicCobject,带有一个字段Dictionary和一个实现ITypedList和IList的ComplexObjectCollection。

这一切都正常,除非我将DataGrid的itemsSource绑定到集合时,单元格将显示SimpleObject类型名称,我实际上想要实现一个模板,以在文本块中显示SimpleObject的属性Value。 / p>

我已经使用各种方法来尝试获取底层的SimpleObject但是没有任何工作,我总是得到行的ComplexObject。我正在使用自动生成的列,这似乎总是产生一个文本列,这可能是问题,但为什么我仍然无法从单元格属性中的某个地方获取底层的SimpleObject?

以下是我理想的解决方案,但这不起作用。

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="DefaultNodeTempate">
            <ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                              Path=Content}">
                <ContentControl.Resources>
                        <DataTemplate DataType="local:SimpleObjectType">
                            <TextBlock Text="{Binding Value}" />
                        </DataTemplate>
                </ContentControl.Resources>
            </ContentControl>
        </DataTemplate>
    </Grid.Resources>
    <DataGrid ItemsSource="{Binding ElementName=mainWin, Path=DynamicObjects}">
        <DataGrid.Resources>
            <Style TargetType="DataGridCell">
                <Setter Property="ContentTemplate" Value="{StaticResource DefaultNodeTempate}" />
            </Style>
        </DataGrid.Resources>
    </DataGrid>
</Grid>

我们非常感谢任何建议。

由于

基兰

1 个答案:

答案 0 :(得分:0)

所以我发现解决方案是在后面的代码中做一些工作。

在AutoGeneratingColumn事件中创建一个带有内容控件和自定义模板选择器的DataTemplate(我在Xaml中创建选择器并将其作为资源发现)。

使用e.PropertyName作为路径为ContentControl的ContentProperty创建绑定

创建一个新的DataGridTemplateColumn并将新列CellTemplate设置为新的DataTemplate

将e.Column替换为您的新列,并将单元格datacontext与该列的动态属性绑定。

如果有人对此有任何改进,请随时分享您的想法。

由于

编辑:根据要求为我的解决方案提供了一些示例代码

自定义模板选择器:

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>

代码背后:

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;
}

可能有更好的方法来创建数据模板,我最近读过微软建议使用XamlReader,但这就是我当时的做法。我还没有在动态类上测试过这个,但我确信它应该以任何方式工作。