WPF Datagrid flickering issue

2019-05-06 08:24发布

问题:

In WPF, I have a DataGrid bound to a DataView in the ViewModel class. It is a touch panel embedded project, so every time I touch and slide my fingers on the panel it keeps sending me values and saves those values to the DataTable and assigns it to the bound DataView in a way where it can show only 5 or 10 rows (predefined) as the data gets updated. Every time I get a new row I delete the last till the total DataTable row count is 5/10.

The issue here is that it is taking longer than usual for the DataGrid to bind to the last values. The moment I lift my hand off the panel, I expect the grid to bind to those values, but it is taking some 6 to 10 seconds to do this operation where the user has to wait for it to complete.

For this, I have used the IsAysnc property in XAML. As expected, this makes the DataGrid bind fast but every time the data gets updated, the DataGrid flickers. How can I overcome the flickering issue in the DataGrid? Or is there any other way to do it. We are following MVVM patterns for the binding. Thanks in advance.

xaml:

     <DataGrid  Grid.Row="1"  HorizontalAlignment="Center" 
VerrticalAlignment="Top" Height="Auto"  Width="Auto" 

        BorderThickness="1" BorderBrush="Black" ColumnHeaderHeight="35" 

RowHeight="30" HorizontalContentAlignment="Center" 

VerticalContentAlignment="Center"AlternationCount="2" 

AlternatingRowBackground="WhiteSmoke"CanUserSortColumns="False"  

CanUserResizeRows="False" HorizontalScrollBarVisibility="Hidden" 

VerticalScrollBarVisibility="Hidden"ItemsSource="{Binding Path = 

View,IsAsync=True,UpdateSourceTrigger=PropertyChanged}" 

Margin="0,20,0,0"AutoGenerateColumns="True"  EnableColumnVirtualization="True" 

EnableRowVirtualization="True" CanUserAddRows="False" >

View Model:

private void InsertCollection(List<string> values)
        {
            if (values == null || !values.Any()) return;

            try
            {
                var dataRow = ObjectMessageDataTable.NewRow();
                int columnCount = ObjectMessageDataTable.Columns.Count;

                var inputs = values.Select(y => y as object).ToArray();
                for (var i = 0; i < inputs.Count() && i < columnCount; i++)
                    dataRow[i] = values[i];
                ObjectMessageDataTable.Rows.InsertAt(dataRow, 0);
                var count = ObjectMessageDataTable.Rows.Count;

                while (count > NumOfRows)
                {
                    ObjectMessageDataTable.Rows.RemoveAt(NumOfRows);
                    count = ObjectMessageDataTable.Rows.Count;
                }

                ObjectMessageDataTable.AcceptChanges();
                View = ObjectMessageDataTable.DefaultView;
            }
            catch (Exception ex)
            {

            }

        }

回答1:

I tried your code. It is so simple to databind the datatable directly and the flickering will go away :). just use ObjectMessageDataTable.DefaultView instead of View. Because somehow the View object itself is created everytime View is created and this causes the datagrid to initialise from the beginning.

 ItemsSource="{Binding Path=ObjectMessageDataTable.DefaultView, IsAsync=True, UpdateSourceTrigger=PropertyChanged}"

so change to

<DataGrid
        Grid.Row="1"
        Width="Auto"
        Height="Auto"
        Margin="0,20,0,0"
        HorizontalAlignment="Center"
        VerticalAlignment="Top"
        HorizontalContentAlignment="Center"
        VerticalContentAlignment="Center"
        AlternatingRowBackground="WhiteSmoke"
        AlternationCount="2"
        AutoGenerateColumns="True"
        BorderBrush="Black"
        BorderThickness="1"
        CanUserAddRows="False"
        CanUserResizeRows="False"
        CanUserSortColumns="False"
        ColumnHeaderHeight="35"
        EnableColumnVirtualization="True"
        EnableRowVirtualization="True"
        HorizontalScrollBarVisibility="Hidden"
        ItemsSource="{Binding Path=ObjectMessageDataTable.DefaultView, IsAsync=True, UpdateSourceTrigger=PropertyChanged}"
        RowHeight="30"
        VerticalScrollBarVisibility="Hidden" />

Hope it helps.