【问题标题】:Problems binding to a the content of a WPF DataGridCell in XAML绑定到 XAML 中 WPF DataGridCell 内容的问题
【发布时间】:2012-09-13 15:20:39
【问题描述】:

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

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 的属性值。

我使用了各种方法来尝试获取底层的 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>

任何建议将不胜感激。

谢谢

基兰

【问题讨论】:

    标签: wpf xaml datagrid datagridcell


    【解决方案1】:

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

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

    为 ContentControl 的 ContentProperty 创建一个绑定,以 e.PropertyName 作为路径

    创建一个新的 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,但这就是我当时的做法。此外,我还没有在动态类上测试过这个,但我确信它应该可以工作。

    【讨论】:

    • 嗨@Kezza,你能在这里分享代码吗?我面临着类似的问题。我正在尝试找到一种方法,如何通过 xaml 中的绑定在单元级别上设置单元格可编辑(isReadOnly)。单元格的值为对象,具有属性值和 isEditable。
    猜你喜欢
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    相关资源
    最近更新 更多