I have a custom class providing 3d-point information with readonly
properties:
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;
}
}
To display multiple 3d-points I use a DataGrid
with four columns in WPF. The first column is supposed to show the row-numbers of the entry.
<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>
To bind a collection of points to the DataGrid
I use a ObservableCollection
:
private ObservableCollection<Point3d> pointList;
The binding is concluded by setting the DataContext
:
this.pointList = new ObservableCollection<Point3d>();
dgrPoints.ItemsSource= this.poseList;
To retrieve the row numbers I use the following converter suggested by Andy in this 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()
{
}
}
This all works fine and sets the according row number in the first column of the DataGrid
whenever a new row (Point3d
) is added. But whenever a row is removed the row-numbers will not update, since the converter is triggered by adding an new DataGridRow
. Right now I force un update by setting the DataGrid.DataContext
to null
and add it again:
this.pointList.RemoveAt(0);
dgrPoints.ItemsSource = null;
dgrPoints.ItemsSource = this.pointList;
This can not be a proper solution to achieve un update for the row numbers. What is the best way to trigger the converter for every row whenever the pointList
changes?
I do not want to use the DataGridRow.Header
property, since this displaces my columns. Correct me if I am wrong. Other than that, every suggestion considering different approaches are welcome.