我有一个绑定到数据网格(MVVM)的类型化数据集。我还有一个点列表(输入数据集中的 X 和 Y),表明哪些单元格有错误。检测这一点的逻辑很复杂并且在服务器端运行。
我的目标是如果每个单元格有错误,则将其背景绘制为不同的颜色(即点列表包含该单元格的 X 和 Y)。
数据网格定义为:
<DataGrid x:Name="gridData" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
BorderThickness="0 0 0 0" Margin="0 0 0 0" AutoGenerateColumns="True" AlternationCount="1" AlternatingRowBackground="AliceBlue"
ItemsSource="{Binding Path=EquisDataTable}" SelectionUnit="Cell" SelectedCellsChanged="gridData_SelectedCellsChanged"
AutoGeneratedColumns="GridData_OnAutoGeneratedColumns" AutoGeneratingColumn="gridData_AutoGeneratingColumn" Height="350">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Setters>
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource onErrorConverter}">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding RelativeSource="{RelativeSource AncestorType=SampleTests:SampleTestUserControlBase}" Path="DataContext.Problems" />
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</DataGrid.CellStyle>
</DataGrid>
我相信我现在已经接近它了(经过大量测试和谷歌搜索才到达这里)。当填充所有内容后更改单元格选择时,我可以找到单元格的 X 和 Y,“SelectedCellsChanged”方法。这并不能让我到达每个单元格并在加载时检查其值。
private void gridData_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
int x;
int y;
if (TryGetDataGridCellXandY(gridData.CurrentCell, gridData, out x, out y))
{ }
}
private bool TryGetDataGridCellXandY(DataGridCellInfo dgc, DataGrid dataGrid, out int x, out int y)
{
int columnIndex = dgc.Column.DisplayIndex;
return TryGetDataGridCellXandY(columnIndex, dataGrid, out x, out y);
}
private bool TryGetDataGridCellXandY(int columnIndex, DataGrid dataGrid, out int x, out int y)
{
DataGridCellInfo currentCell = dataGrid.CurrentCell;
int rowIndex = int.MinValue;
DataRowView rowView = currentCell.Item as DataRowView;
if (rowView != null)
{
DataRow dataRow = rowView.Row;
FieldInfo fi = typeof(DataRow).GetField("_rowID", BindingFlags.NonPublic | BindingFlags.Instance);
try
{
if (fi != null)
{
rowIndex = System.Convert.ToInt32(fi.GetValue(dataRow));
}
}
catch (InvalidCastException) { }
}
x = columnIndex;
y = rowIndex;
return x > 0 && y > 0;
}
所以我创建了一个多值转换器来完成同样的事情。使用转换器时,当单元格的列为空时,就会出现问题,并且 currentCell.Item (DataGridCellInfo).Item 将具有 {DependencyProperty.UnsetValue}。
public class DataGridCellOnErrorConversion : IMultiValueConverter
{
private const string DefaultColour = "White";
private const string ErrorColour = "Red";
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length != 3)
return DefaultColour;
DataGridCell dgc = values[0] as DataGridCell;
if(dgc == null)
return DefaultColour;
IList<Point> problems = values[1] as IList<Point>;
if(problems == null)
return DefaultColour;
DataGrid grid = values[2] as DataGrid;
if (grid == null)
return DefaultColour;
int x;
int y;
if (TryGetDataGridCellXandY(grid.CurrentCell, grid, out x, out y))
{
if (problems.Any(problem => System.Convert.ToInt32(problem.X) == x && System.Convert.ToInt32(problem.Y) == y))
{
return ErrorColour;
}
}
return DefaultColour;
}
private bool TryGetDataGridCellXandY(DataGridCellInfo dgc, DataGrid dataGrid, out int x, out int y)
{
int columnIndex = dgc.Column.DisplayIndex;
return TryGetDataGridCellXandY(columnIndex, dataGrid, out x, out y);
}
private bool TryGetDataGridCellXandY(int columnIndex, DataGrid dataGrid, out int x, out int y)
{
DataGridCellInfo currentCell = dataGrid.CurrentCell;
int rowIndex = int.MinValue;
DataRowView rowView = currentCell.Item as DataRowView;
if (rowView != null)
{
DataRow dataRow = rowView.Row;
FieldInfo fi = typeof(DataRow).GetField("_rowID", BindingFlags.NonPublic | BindingFlags.Instance);
try
{
if (fi != null)
{
rowIndex = System.Convert.ToInt32(fi.GetValue(dataRow));
}
}
catch (InvalidCastException) { }
}
x = columnIndex;
y = rowIndex;
return x > 0 && y > 0;
}
}
这是因为绑定/创建顺序吗?有没有解决的办法?
Thanks