滚动时 Datagrid 行为异常
Datagrid acting weirdly when scrolling
编辑:我注意到问题不在第一行,而是鼠标滚动后所有行都移动了。
我完全清楚这是一个棘手的问题,可能会导致我提出不完整或过于个人化的问题。那就是说我会尽可能清楚地解释它。
我有一个数据网格,它是我通过例程构建的。如果需要我可以分享。之后数据网格通过事件进行转换:
<DataGrid Name="dtgResults" Background="Transparent" CanUserSortColumns="False" IsReadOnly="True" Foreground="Black" LoadingRow="Datagrid_LoadingRow">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<EventSetter Event="DataGridCell.Loaded" Handler="DataGridCell_Load"/>
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</DataGrid.Resources>
</DataGrid>
即:
在Datagrid_LoadingRow
int index = row.GetIndex();
if (obcMyDim[index].IsComment) <-----a matrix telling when it's a comment
row.Foreground = new SolidColorBrush(Colors.White);
else
row.Foreground = new SolidColorBrush(Colors.Black);
所以这只是一个着色问题,没有更改单元格数据!
在 DataGridCell_Load 中,我设置了小数位数的格式并通过以下方式实现:
DataGridCell cell = sender as DataGridCell;
DataGrid parentDataGrid = (DataGrid)(cell.Tag);
int column = cell.Column.DisplayIndex;// da 0
int row = -1;
//I get the line
DependencyObject rowDO = cell as DependencyObject;
while (rowDO != null && !(rowDO is DataGridRow))
rowDO = VisualTreeHelper.GetParent(rowDO);
if (rowDO != null)
{
DataGridRow gridrow = (DataGridRow)rowDO;
row = gridrow.GetIndex();
}
...
string strCellContent = ((TextBlock)cell.Content).Text;
if (strCellContent.Trim() != string.Empty)
{
if (strCellContent.IsNumeric())<----custom function
{
dVal = double.Parse(strCellContent, CultureInfo.InvariantCulture);
((TextBlock)cell.Content).Text = dVal.ToString("0.0000");
bool condOutOfTolerance = ...;
//Errore
if (column >= 5 && condOutOfTolerance)
cell.Foreground = new SolidColorBrush(Colors.Red);
}
}
所以简而言之,问题是第一行在
之后表现得很奇怪
这是第一张正确的图片。
然后在 滚动后 up/down 数据网格第一行发生变化
然后再次不同
我感觉这是刷新问题,但我不明白如何解决。
感谢您的帮助
帕特里克
----添加----
以下是我手动填充数据网格的方法:
public void SynchronizeDtgResults(DataGrid dtg)
{
/*-----------------------------------------------*
* manuale generation HEADER / COLUMNS / ROWS *
*-----------------------------------------------*/
if (obcMyDim == null || obcMyDim.Count() == 0 || obcMyDim[0].obcItemsName == null || obcMyDim[0].obcItemsName.Count() == 0)
{
Serializers.Logger.WriteLog("WARNING SynchronizeDtgResults called with obcmMyDim not valid");
return;
}
int numColonneFisse = 5; //Num, name, nominal, ut, ul
int numParts = obcMyDim[0].obcItemsName.Count();//refer to the first coz are all the same
int numTotaleColonne = numColonneFisse + numParts;
int numTotaleRighe = obcMyDim.Count;
string[] columnLabels = new string[numTotaleColonne];
//1. Header Preparation
// first 5 fixed col
columnLabels[0] = Languages.Word(eWords.Num);
columnLabels[1] = Languages.Word(eWords.Name);
columnLabels[2] = Languages.Word(eWords.Nominal);
columnLabels[3] = Languages.Word(eWords.UT);
columnLabels[4] = Languages.Word(eWords.LT);
// and then the names of the parts
for (int iii = 0; iii < numParts; iii++)
columnLabels[iii + numColonneFisse] = obcMyDim[0].obcItemsName[iii];
//2. Clean and add header
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Columns.Clear(); }));
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Items.Clear(); }));
var styleHeaderDatagrid = new Style(typeof(System.Windows.Controls.Primitives.DataGridColumnHeader));
styleHeaderDatagrid.Setters.Add(new Setter { Property = BorderBrushProperty, Value = Brushes.Black });
styleHeaderDatagrid.Setters.Add(new Setter { Property = BorderThicknessProperty, Value = new Thickness(1) });
styleHeaderDatagrid.Setters.Add(new Setter { Property = ForegroundProperty, Value = Brushes.Black });
styleHeaderDatagrid.Setters.Add(new Setter { Property = FontWeightProperty, Value = FontWeights.Bold });
styleHeaderDatagrid.Setters.Add(new Setter { Property = MarginProperty, Value = new Thickness(2) });
var tb = new TextBlock() { FontSize = dtg.FontSize, FontFamily = dtg.FontFamily };
reportDimensionNameWidth = 0;
foreach (var item in obcMyDim)
{
tb.Text = item.NameAxisDimension;
double dim = GraphicExtensions.GetTextBlockSize(tb).Width;
if (dim > reportDimensionNameWidth)
reportDimensionNameWidth = dim + 20;
}
foreach (string label in columnLabels)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Header = label;
column.HeaderStyle = styleHeaderDatagrid;
column.Binding = new Binding(label.Replace(' ', '_'));
column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Columns.Add(column); }));
}
//3 adding rows
int num = 1;
for (int riga = 0; riga < numTotaleRighe; riga++)
{
dynamic newRow = new ExpandoObject();
//Adding dimension per each row
for (int colonna = 0; colonna < numTotaleColonne; colonna++)
{
string strColumnHeader = columnLabels[colonna].Replace(' ', '_');
((IDictionary<String, Object>)newRow)[strColumnHeader] = string.Empty;
switch (colonna)
{
//Here fixed lines
case 0: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = num++; break;
case 1: ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].NameAxisDimension; break;
case 2: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].Nominal; break;
case 3: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].UpperTolerance; break;
case 4: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].LowerTolerance; break;
//Here all data
default:
if (!obcMyDim[riga].IsComment)
{
if (colonna < numTotaleColonne)
{
if ((colonna - numColonneFisse < 0) || (colonna - numColonneFisse) > obcMyDim[riga].obcItemsMeasured.Count)
{
string str = "Wrong num column obcMyDim idx=" + (colonna - numColonneFisse) + " obcmMyDim[" + riga + "].obcItemsMeasured.Count= " + obcMyDim[riga].obcItemsMeasured.Count;
MessageBox.Show(str);
}
else
((IDictionary<String, Object>)newRow)[strColumnHeader] = (obcMyDim[riga].obcItemsMeasured[colonna - numColonneFisse]).ToString();
}
else
MessageBox.Show("DtgResult Wrong column number: " + colonna);
}
break;
}
}
Serializers.Logger.WriteLog("SynchronizeDtgResults added new row num=" + riga + " name=" + obcMyDim[riga].NameAxisDimension);
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Items.Add(newRow); }));
}
Serializers.Logger.WriteLog("SynchronizeDtgResults END");
}
再次感谢您的帮助!!!
这似乎是与以下其中一项相关的问题。如何在数据网格中填充数据或如何处理行索引。当您滚动时,这会导致数据网格刷新和更新。
要测试的几件事是关闭数据虚拟化并查看 DataGridCell_Load。如果关闭数据虚拟化也无济于事。 DataGridCell_Load.
存在一些逻辑错误
能否请您添加任何可以 transform/modify 数据网格的额外代码?
最终的解决方案是数据虚拟化。
我刚刚遇到了同样的问题。滚动网格将开始发送 ColorPicker
控件的 SelectedColorChanged
事件、DataGrid
的 CellEditEnding
事件以及 DataGridComboBoxColumn
的一些事件。如解决方案中所述,关闭 DataGrid
的 EnableRowVirtualization
和 EnableColumnVirtualization
属性确实解决了问题。
编辑:我注意到问题不在第一行,而是鼠标滚动后所有行都移动了。
我完全清楚这是一个棘手的问题,可能会导致我提出不完整或过于个人化的问题。那就是说我会尽可能清楚地解释它。 我有一个数据网格,它是我通过例程构建的。如果需要我可以分享。之后数据网格通过事件进行转换:
<DataGrid Name="dtgResults" Background="Transparent" CanUserSortColumns="False" IsReadOnly="True" Foreground="Black" LoadingRow="Datagrid_LoadingRow">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<EventSetter Event="DataGridCell.Loaded" Handler="DataGridCell_Load"/>
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</DataGrid.Resources>
</DataGrid>
即:
在Datagrid_LoadingRow
int index = row.GetIndex();
if (obcMyDim[index].IsComment) <-----a matrix telling when it's a comment
row.Foreground = new SolidColorBrush(Colors.White);
else
row.Foreground = new SolidColorBrush(Colors.Black);
所以这只是一个着色问题,没有更改单元格数据!
在 DataGridCell_Load 中,我设置了小数位数的格式并通过以下方式实现:
DataGridCell cell = sender as DataGridCell;
DataGrid parentDataGrid = (DataGrid)(cell.Tag);
int column = cell.Column.DisplayIndex;// da 0
int row = -1;
//I get the line
DependencyObject rowDO = cell as DependencyObject;
while (rowDO != null && !(rowDO is DataGridRow))
rowDO = VisualTreeHelper.GetParent(rowDO);
if (rowDO != null)
{
DataGridRow gridrow = (DataGridRow)rowDO;
row = gridrow.GetIndex();
}
...
string strCellContent = ((TextBlock)cell.Content).Text;
if (strCellContent.Trim() != string.Empty)
{
if (strCellContent.IsNumeric())<----custom function
{
dVal = double.Parse(strCellContent, CultureInfo.InvariantCulture);
((TextBlock)cell.Content).Text = dVal.ToString("0.0000");
bool condOutOfTolerance = ...;
//Errore
if (column >= 5 && condOutOfTolerance)
cell.Foreground = new SolidColorBrush(Colors.Red);
}
}
所以简而言之,问题是第一行在
之后表现得很奇怪这是第一张正确的图片。
然后在 滚动后 up/down 数据网格第一行发生变化
然后再次不同
我感觉这是刷新问题,但我不明白如何解决。
感谢您的帮助
帕特里克 ----添加----
以下是我手动填充数据网格的方法:
public void SynchronizeDtgResults(DataGrid dtg)
{
/*-----------------------------------------------*
* manuale generation HEADER / COLUMNS / ROWS *
*-----------------------------------------------*/
if (obcMyDim == null || obcMyDim.Count() == 0 || obcMyDim[0].obcItemsName == null || obcMyDim[0].obcItemsName.Count() == 0)
{
Serializers.Logger.WriteLog("WARNING SynchronizeDtgResults called with obcmMyDim not valid");
return;
}
int numColonneFisse = 5; //Num, name, nominal, ut, ul
int numParts = obcMyDim[0].obcItemsName.Count();//refer to the first coz are all the same
int numTotaleColonne = numColonneFisse + numParts;
int numTotaleRighe = obcMyDim.Count;
string[] columnLabels = new string[numTotaleColonne];
//1. Header Preparation
// first 5 fixed col
columnLabels[0] = Languages.Word(eWords.Num);
columnLabels[1] = Languages.Word(eWords.Name);
columnLabels[2] = Languages.Word(eWords.Nominal);
columnLabels[3] = Languages.Word(eWords.UT);
columnLabels[4] = Languages.Word(eWords.LT);
// and then the names of the parts
for (int iii = 0; iii < numParts; iii++)
columnLabels[iii + numColonneFisse] = obcMyDim[0].obcItemsName[iii];
//2. Clean and add header
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Columns.Clear(); }));
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Items.Clear(); }));
var styleHeaderDatagrid = new Style(typeof(System.Windows.Controls.Primitives.DataGridColumnHeader));
styleHeaderDatagrid.Setters.Add(new Setter { Property = BorderBrushProperty, Value = Brushes.Black });
styleHeaderDatagrid.Setters.Add(new Setter { Property = BorderThicknessProperty, Value = new Thickness(1) });
styleHeaderDatagrid.Setters.Add(new Setter { Property = ForegroundProperty, Value = Brushes.Black });
styleHeaderDatagrid.Setters.Add(new Setter { Property = FontWeightProperty, Value = FontWeights.Bold });
styleHeaderDatagrid.Setters.Add(new Setter { Property = MarginProperty, Value = new Thickness(2) });
var tb = new TextBlock() { FontSize = dtg.FontSize, FontFamily = dtg.FontFamily };
reportDimensionNameWidth = 0;
foreach (var item in obcMyDim)
{
tb.Text = item.NameAxisDimension;
double dim = GraphicExtensions.GetTextBlockSize(tb).Width;
if (dim > reportDimensionNameWidth)
reportDimensionNameWidth = dim + 20;
}
foreach (string label in columnLabels)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Header = label;
column.HeaderStyle = styleHeaderDatagrid;
column.Binding = new Binding(label.Replace(' ', '_'));
column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Columns.Add(column); }));
}
//3 adding rows
int num = 1;
for (int riga = 0; riga < numTotaleRighe; riga++)
{
dynamic newRow = new ExpandoObject();
//Adding dimension per each row
for (int colonna = 0; colonna < numTotaleColonne; colonna++)
{
string strColumnHeader = columnLabels[colonna].Replace(' ', '_');
((IDictionary<String, Object>)newRow)[strColumnHeader] = string.Empty;
switch (colonna)
{
//Here fixed lines
case 0: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = num++; break;
case 1: ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].NameAxisDimension; break;
case 2: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].Nominal; break;
case 3: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].UpperTolerance; break;
case 4: if (!obcMyDim[riga].IsComment) ((IDictionary<String, Object>)newRow)[strColumnHeader] = obcMyDim[riga].LowerTolerance; break;
//Here all data
default:
if (!obcMyDim[riga].IsComment)
{
if (colonna < numTotaleColonne)
{
if ((colonna - numColonneFisse < 0) || (colonna - numColonneFisse) > obcMyDim[riga].obcItemsMeasured.Count)
{
string str = "Wrong num column obcMyDim idx=" + (colonna - numColonneFisse) + " obcmMyDim[" + riga + "].obcItemsMeasured.Count= " + obcMyDim[riga].obcItemsMeasured.Count;
MessageBox.Show(str);
}
else
((IDictionary<String, Object>)newRow)[strColumnHeader] = (obcMyDim[riga].obcItemsMeasured[colonna - numColonneFisse]).ToString();
}
else
MessageBox.Show("DtgResult Wrong column number: " + colonna);
}
break;
}
}
Serializers.Logger.WriteLog("SynchronizeDtgResults added new row num=" + riga + " name=" + obcMyDim[riga].NameAxisDimension);
Application.Current.Dispatcher.Invoke((Action)(() => { dtg.Items.Add(newRow); }));
}
Serializers.Logger.WriteLog("SynchronizeDtgResults END");
}
再次感谢您的帮助!!!
这似乎是与以下其中一项相关的问题。如何在数据网格中填充数据或如何处理行索引。当您滚动时,这会导致数据网格刷新和更新。
要测试的几件事是关闭数据虚拟化并查看 DataGridCell_Load。如果关闭数据虚拟化也无济于事。 DataGridCell_Load.
存在一些逻辑错误能否请您添加任何可以 transform/modify 数据网格的额外代码?
最终的解决方案是数据虚拟化。
我刚刚遇到了同样的问题。滚动网格将开始发送 ColorPicker
控件的 SelectedColorChanged
事件、DataGrid
的 CellEditEnding
事件以及 DataGridComboBoxColumn
的一些事件。如解决方案中所述,关闭 DataGrid
的 EnableRowVirtualization
和 EnableColumnVirtualization
属性确实解决了问题。