1

我有一个复杂的数据表(大约 150 行,1 到 100 列之间),我想在 WPF 中使用 DataGrid 显示和编辑它,但我遇到了一个很大的绊脚石。如果我的术语有问题,请原谅我(并纠正我),因为我对 WPF 和 XAML 还很陌生。

为了理解我的问题,我的要求是:

  • 数据由可变数量的行和列组成,这些行和列通过 AJAX 加载
  • 每行(我的测试实现中的“记录”类)都有一些需要显示的固定属性以及集合中不同数量的属性(尽管所有行都具有相同数量的此类属性)
  • 每行/记录都有一个类型(例如,字符串、整数、布尔值),用于通过枚举属性“VType”推断出的属性。应根据 VType 值使用模板显示和编辑属性。
  • 可以在运行时添加或删除列
  • (某些)行也可以在运行时添加或删除
  • 行可以在运行时改变它们的“类型”

到目前为止,我已经使用 DataGridTextColumns 构建了一个工作示例,该示例从模拟数据创建列并填充绑定的集合。我已经实现了 INotifyPropertyChanged 并在必要时使用了 ObservableCollections,因此反应性有效,并且我的属性值从绑定中提取到单个属性并正确显示。

添加列时,我通过了正确的绑定。对于我的示例应用程序,我使用列索引将每一列绑定到 Record 集合中的正确 Property 对象:

    // Amounts to "Properties[0].Value", "Properties[1].Value", etc.
    var binding = new Binding(string.Format("Properties[{0}].Value", column.Index));
    dataGrid.Columns.Add(new DataGridTextColumn() { Header = column.Name, Binding = binding });

现在我尝试为不同的“记录类型”使用不同的模板,即我的记录类中的 vType 属性。我在 Window.Resources 中创建了数据模板(开始时非常粗糙),设置了查找并实现了 RecordTemplateSelector:

    <!--BOOL TEMPLATE-->
    <DataTemplate x:Key="booleanTemplate">
        <CheckBox IsChecked="{Binding Value}" Background="LightGray" Margin="5, 0, 0, 0"/>
    </DataTemplate>

    <!--STRING TEMPLATE-->
    <DataTemplate x:Key="stringTemplate">
        <TextBlock Text="{Binding Value}"/>
    </DataTemplate>

    <!--INTEGER TEMPLATE-->
    <DataTemplate x:Key="integerTemplate">
        <TextBlock Text="{Binding Value}"/>
    </DataTemplate>

    <local:RecordTemplateSelector x:Key="myRecordTemplateSelector"
                                      BooleanTemplate="{StaticResource booleanTemplate}"
                                      StringTemplate="{StaticResource stringTemplate}"
                                      IntegerTemplate="{StaticResource integerTemplate}"/>

这是我的模板选择器:

    class RecordTemplateSelector : DataTemplateSelector
    {
        public DataTemplate StringTemplate { get; set; }

        public DataTemplate BooleanTemplate { get; set; }

        public DataTemplate IntegerTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var selectedTemplate = StringTemplate;

            var record = item as Record;

            if (item == null) return selectedTemplate;

            switch (record.VType)
            {
                case Record.ValueType.Checkbox:
                    selectedTemplate = BooleanTemplate;
                    break;

                case Record.ValueType.Integer:
                    selectedTemplate = IntegerTemplate;
                    break;

                case Record.ValueType.String:
                    selectedTemplate = StringTemplate;
                    break;
            }

            return selectedTemplate;
        }
    }

它确实提取了正确的模板,但是当我认为我让它工作时,我注意到我无法正确绑定我的 DataGridTemplateColumn - 它总是隐式绑定到整行(即 Record 对象)并且我看不到方法我的模板如何知道它应该应用于 Record 的 Property 集合中的哪个元素。

我不知道从这里去哪里。有没有办法将列的绑定继承到模板?有没有其他方法可以将正确的项目(索引也可以)传递给模板?还是我必须使用完全不同的方法?

非常感谢您给我的任何意见。

4

0 回答 0