我有一个复杂的数据表(大约 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 集合中的哪个元素。
我不知道从这里去哪里。有没有办法将列的绑定继承到模板?有没有其他方法可以将正确的项目(索引也可以)传递给模板?还是我必须使用完全不同的方法?
非常感谢您给我的任何意见。