【问题标题】:DataTemplate is not recognized for DataGrid itemsDataGrid 项目无法识别 DataTemplate
【发布时间】:2020-07-11 16:17:35
【问题描述】:

我尝试使用 DataGrid 控件在 WPF 中创建类似矩阵的视图。我使用通过转换器可用的 DataTable 填充我的项目源列表。每行都是一个自定义类类型 (MatrixCell) 的数组。 在 xaml 中,在我的资源选项卡中,我为我的类型 MatrixCell 创建了一个 DataTemplate,但是在运行应用程序时它没有被应用。有谁知道我做错了什么?

我的数据网格:

<DataGrid
            CanUserAddRows="False" 
            CanUserDeleteRows="False" 
            CanUserReorderColumns="False" 
            CanUserSortColumns="False" 
            CanUserResizeColumns="False"
            SelectionUnit="Cell"
            IsReadOnly="True"
            Name="matrixGrid">
            <DataGrid.ItemsSource>
                <Binding Path="Test" Converter="{StaticResource MatrixToDataViewConverter}"/>
            </DataGrid.ItemsSource>
            <DataGrid.ColumnHeaderStyle>
                <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
                    <Setter Property="LayoutTransform">
                        <Setter.Value>
                            <TransformGroup>
                                <RotateTransform Angle="270"/>
                            </TransformGroup>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGrid.ColumnHeaderStyle>
        </DataGrid>

我的转换器:

public class MatrixToDataViewConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var myDataTable = new System.Data.DataTable();
            if(value != null)
            {
                var test = value as ITest;
                myDataTable.Columns.Add("-");
                foreach (var column in test.Columns)
                {
                    //populate columns
                    //...
                }

                var rows = new List<List<MatrixCell>>();
                foreach (var matrixRow in test.MatrixRows)
                {
                    var row = new List<MatrixCell>();
                    row.Add(new MatrixCell() { Content = $"{matrixRow.Id} {matrixRow.Name}" });
                    var temp = new MatrixCell[1 + test.Columns.Count];
                    foreach (var column in test.Columns)
                    {
                        //determine the Content value for each MatrixCell
                        //...
                        row.Add(new MatrixCell() { Content = content });
                    }

                    row.CopyTo(temp);
                    myDataTable.Rows.Add(temp);
                }
            }
            return myDataTable.DefaultView;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

MatrixCell 类:

public class MatrixCell
    {
        public string Content { get; set; }

        public bool IsComparerDone { get; set; }

        //public override string ToString()
        //{
        //    return Content;
        //}
    }

数据模板:

<DataTemplate DataType="{x:Type viewModels:MatrixCell}">
            <TextBlock Text="{Binding Content}">
                <!--<TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsComparerResult}" Value="True">
                                <Setter Property="Background" Value="Yellow"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>-->
            </TextBlock>
</DataTemplate>

只是为了显示 MatrixCell.Content 我可以覆盖 ToString 方法并且它可以工作,但我想使用 DataTemplate 来做到这一点。

这是我当前应用程序的外观: matrix view

【问题讨论】:

    标签: c# wpf datatable datagrid datatemplate


    【解决方案1】:

    欢迎来到 SO!如果您提供MVCE,以供将来参考,您将获得更好的答案,但我会尽力提供帮助...

    你不需要那个转换器。只需直接绑定到您的列表并显式声明 DataGridTemplateColumn 类型的列。然后在那个地方放置一个ContentControl 并将其Content 属性绑定到它当前的DataContext(即Content="{Binding}")。然后,ContentControl 将选择您的 DataTemplate 并相应地填充自己。

    【讨论】:

    • 感谢您的回答。但我确实需要那个转换器。我没有将我的 ItemsSource 绑定到的列表,但更重要的是,我每次都必须根据我的“测试”文件重新创建我的列。我知道如何做到这一点的唯一方法是使用转换器。
    • 您已经标记了data-binding,但您实际上并没有进行数据绑定,至少不是 WPF 设计使用它的方式。您确实有一个项目列表:ITest.MatrixRows。通过数据绑定,您可以以视图可以轻松使用的格式准备数据,当数据转换必须双向进行时(与通常使用 DataTriggers 的单向相反),转换器用于轻量级任务。业务逻辑永远不会进入转换器,这始终表明负责准备数据以供您的视图使用的层没有正常工作。
    • 因此,在您的情况下,您将声明一个类调用 MatrixRow 或包含 MatrixCell 类型列表的东西。您的业​​务层创建这些列表,并使用适当的内容填充每个 MatrixCell 列表。这个List&lt;MatrixRow&gt; 是您将 ItemsSource 绑定到的对象。实际上,您或多或少地在做正确的事情,只是在错误的地方做,这导致您还必须手动创建子控件。通过适当的数据绑定,DataTemplates 会为您完成这项工作,您只需提供数据并让它负责繁重的工作。
    • 对不起,忽略关于您手动创建控件的最后一点,再次查看它,我发现这实际上不是您在做什么。我所说的其余部分仍然有效......将数据转换为 DataTable 应该在 ItemsSource 绑定到的层中完成,而不是在转换器内。
    猜你喜欢
    • 2011-10-19
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多