Patrick
Patrick

Reputation: 2593

Datagrid acting weirdly when scrolling


EDIT : I have been led to notice that the problem is not on the first line but all lines are shifted after mouse scrolling.


I am perfectly aware that this is a tricky problem which might lead me to an incomplete or too personal question. That said I'll try to explain it as clearly as possible. I have a datagrid which is build by me through a routine. If necessary I can share it. After that the datagrid undergoes transformations through events:

<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>

that is:


in 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);

so it's just a colouring matter no cell data change!


in DataGridCell_Load instead i format the number of decimals and make through this:

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);
    }
}

So in short the problem is that the FIRST LINE behaves weirdly after having

This is the first and correct image. enter image description here

then after having scrolled up/down the datagrid the first line changes

enter image description here

and then again differently

enter image description here

I get the feeling that somehow it's a matter of refresh but I can't understand how to fix that.

Thank you for any help

Patrick ----ADD----

Here is how I manually populate my datagrid:

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");
}

Again thanks for helping!!!!

Upvotes: 0

Views: 1260

Answers (2)

XtremeCold
XtremeCold

Reputation: 27

I just had the same problem. Scrolling the grid would start sending SelectedColorChanged event of the ColorPicker control, CellEditEnding event of the DataGrid, and some events of the DataGridComboBoxColumn. Turning off EnableRowVirtualization and EnableColumnVirtualization properties of the DataGrid as mentioned in the solution really solved the issue.

Upvotes: 0

peterpep
peterpep

Reputation: 324

This looks to be a problem related to one of the following. How the data is being populated in the data grid or how the row index is being handled. When you scroll, this causes the datagrid to refresh and update.

A couple of things to test is to turn off datavirtualization and to review DataGridCell_Load. If data virtualization being turned off does not help. There is some logic error with DataGridCell_Load.

Can you please add any additional code that can transform/modify the datagrid?

Final solution was turn of data virtualization.

Upvotes: 2

Related Questions