Производительность вертикальной полосы прокрутки WPF DataGrid и размещение элементов в таблице для очень медленной визуализации - PullRequest
0 голосов
/ 15 апреля 2020

Я работаю над приложением для отображения данных журнала andorid в режиме реального времени, каждый раз, когда я подключаю устройство для отображения журнала, сначала будут отображаться данные журнала в кеше, около 100 000 строк журнала. Когда я отображал журнал, я использовал привязку данных, но это было не так быстро, как я думал, мне потребовалось более 1 минуты, чтобы отобразить около 100 000 строк журнала на сетке данных, и пока он отображал данные, вертикальная полоса прокрутки очень медленная и запаздывает. Горизонтальная полоса прокрутки такая же, и моя таблица состоит из 7 столбцов. Пожалуйста, помогите мне улучшить описанную выше ситуацию. Есть ли другой способ ускорить отображение данных и повысить производительность полос прокрутки? Вот мой код:

MainWindow_LogViewDataGrid.xaml

<UserControl x:Class="SmartLogAnalyze.MVVM.UserControls.MainWindow_LogViewDataGrid"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:SmartLogAnalyze.MVVM.UserControls"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"> 
<DataGrid AutoGenerateColumns="False"  CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" IsReadOnly="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" ItemsSource="{Binding LogItemVMs, IsAsync=True}"
          x:Name="datagrid" EnableColumnVirtualization="True" EnableRowVirtualization ="True" 
          VirtualizingStackPanel.IsVirtualizing ="True" VirtualizingStackPanel.VirtualizationMode="Recycling"
          VirtualizingPanel.ScrollUnit="Pixel" GridLinesVisibility="None" Margin="0,3,2,5">
<DataGrid.Columns>
        <DataGridTemplateColumn Header="Line" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Line,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Date" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Date,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Time" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Time,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="LogLV" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Level,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Pid" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Pid,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Tid" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Tid,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Tag" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Tag,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Message" Width="auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Message,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

И это класс для добавления данных в таблицу и отображения: RunFeaturenAction.cs

class RunFeatureAction : IAction
{
    private static string _device = "";
    private static string _command = "";
    private static MainWindowVM _model;
    private static Process _proc;

    private StateController _stateController = StateController.Instance;
    private ComboBox _cbxCommand;
    private ListBox _listbxDevice;

    private Thread _parsingThread = new Thread(() =>
    {
        string line = "abc";
        try
        {
            _proc.Start();

            //Parsing log and add it to datagrid here
            while ((line = _proc.StandardOutput.ReadLine()) != null)
            {
                LogInfo lif = LogInfoManager.Instance.ParseLogInfos(line, _model.LogCount);
                if (lif != null)
                {

                    LogItemVM livm = new LogItemVM(lif);

                    App.Current.Dispatcher.Invoke(()=>
                    {
                        _model.LogItemVMs.Add(livm);
                        _model.LogCount++;
                    });

                }

                StateController.Instance.PausingEvent.WaitOne();

                if (StateController.Instance.StopEvent.WaitOne(0))
                    break;
            }
            _proc.WaitForExit();
        }
        catch
        {
        }
        finally
        {
            if (!_proc.HasExited)
                _proc.Kill();
        }
    });

    public bool Execute(object[] dataTransfer)
    {
        _model = (MainWindowVM)dataTransfer[0];

        var items = (object[])dataTransfer[1];
        _cbxCommand = (ComboBox)items[0];
        _listbxDevice = (ListBox)items[1];

        if (!IsNeedToUpdateRunningState())
        {
            MessageBoxUtil.ShowWarning("Choose device and run again.");
            return false;
        }
        else if (_model.LstDevice.Count == 1)
        {
            _device = _model.LstDevice[0].getSerialNumber();
            _command = _cbxCommand.Text;
        }
        else
        {
            _device = _model.LstDevice[_listbxDevice.SelectedIndex].getSerialNumber();
            _command = _cbxCommand.Text;
        }
        StateController.Instance.UpdateRunningState();

        CheckNeedToResetLogCount();

        return true;
    }

    private bool IsNeedToUpdateRunningState()
    {
        return !((_listbxDevice.SelectedIndex == -1 && _model.LstDevice.Count > 1)
            || _model.LstDevice.Count == 0);
    }

    private void CreateProcces()
    {
        if (!_device.Equals("") && !_command.Equals(""))
            _proc = CommandImpl.Instance.CreateProcess(" -s " + _device + " " + _command);
        else
            _proc = CommandImpl.Instance.CreateProcess(" logcat");
    }

    private void CheckNeedToResetLogCount()
    {
        if (_model == null)
        {
            return;
        }

        if (_stateController.PreState == StateLevel.NONE || _stateController.PreState == StateLevel.STOP)
        {
            StateController.Instance.Start();

            CreateProcces();

            _model.LogCount = 0;
            _model.LogItemVMs.Clear();
            _model.IsRunning = true;

            _parsingThread.Start();

        }
        else if (_stateController.PreState == StateLevel.PAUSING)
        {
            StateController.Instance.Resume();

            _model.IsRunning = true;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...