【发布时间】:2017-11-29 10:04:48
【问题描述】:
我有一个自定义类,通过readonly 属性提供 3d 点信息:
public class Point3d
{
private readonly double x;
public double X { get { return x; } }
private readonly double y;
public double Y { get { return y; } }
private readonly double z;
public double Z { get { return z; } }
public PoseCartesian(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
为了显示多个 3d 点,我在 WPF 中使用了带有四列的DataGrid。第一列应该显示条目的行号。
<DataGrid Name="dgrPoints" AutoGenerateColumns="False"
ItemsSource="{Binding UpdateSourceTrigger=Default, Mode=OneWay}"
SelectionChanged="dgr_Poses_SelectionChanged" CanUserSortColumns="False"
IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn x:Name="colI" Binding="{Binding Mode=OneWay,
RelativeSource={RelativeSource AncestorType=DataGridRow},
Converter={local:RowToIndexConverter}}"/>
<DataGridTextColumn x:Name="colX" Binding="{Binding X}" Header="X"/>
<DataGridTextColumn x:Name="colY" Binding="{Binding Y}" Header="Y"/>
<DataGridTextColumn x:Name="colZ" Binding="{Binding Z}" Header="Z"/>
</DataGrid.Columns>
</DataGrid>
要将点集合绑定到DataGrid,我使用ObservableCollection:
private ObservableCollection<Point3d> pointList;
通过设置DataContext结束绑定:
this.pointList = new ObservableCollection<Point3d>();
dgrPoints.ItemsSource= this.poseList;
要检索行号,我使用Andy 在此answer 中建议的以下转换器:
public class RowToIndexConverter : MarkupExtension, IValueConverter
{
static RowToIndexConverter converter;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DataGridRow row = value as DataGridRow;
if (row != null)
return row.GetIndex() + 1;
else
return -1;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (converter == null) converter = new RowToIndexConverter();
return converter;
}
public RowToIndexConverter()
{
}
}
这一切正常,并在添加新行 (Point3d) 时在 DataGrid 的第一列中设置相应的行号。但无论何时删除一行,行号都不会更新,因为转换器是通过添加新的DataGridRow 来触发的。现在我通过将DataGrid.DataContext 设置为null 来强制取消更新并再次添加:
this.pointList.RemoveAt(0);
dgrPoints.ItemsSource = null;
dgrPoints.ItemsSource = this.pointList;
这不是实现行号取消更新的正确解决方案。每当pointList 更改时,为每一行触发转换器的最佳方法是什么?
我不想使用DataGridRow.Header 属性,因为这会取代我的列。如果我错了,请纠正我。除此之外,我们欢迎所有考虑不同方法的建议。
【问题讨论】: