滚动时 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 事件、DataGridCellEditEnding 事件以及 DataGridComboBoxColumn 的一些事件。如解决方案中所述,关闭 DataGridEnableRowVirtualizationEnableColumnVirtualization 属性确实解决了问题。