TextFile的Lifeupdate DataGrid具有良好的性能 [英] Lifeupdate DataGrid from TextFile with good performance

查看:87
本文介绍了TextFile的Lifeupdate DataGrid具有良好的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

实际状态:

我有一个带有4列的DataGrid(Icon | DateTime | LogLevel | Message)

I have a DataGrid with 4 Columns (Icon|DateTime|LogLevel|Message)

我用它作为查看器来呈现LogFile的条目. 当打开Window时,UI滞后,并且很多条目都被逐个添加到DataGrid.

I use it as a viewer to present entries of a LogFile. When opening the Window the UI lags and alot of entries are added one by one to the DataGrid.

注意:我已经在使用多个线程.我的UI线程未冻结.它只是需要很长时间才能填满整个DataGrid.

Note: I am already using multiple threads. My UI-Thread is not freezing. Its just taking way to long to fill the whole DataGrid.

我想要的东西:

在将其显示给用户之前,我希望在整个窗口中进行预渲染"之类的操作.

I would prefer something like "pre-render" the whole window before showing it to the user.

当我用Aready一次打开Window时-每次我再次打开它时,都没有问题了.(不呈现新的....?)

When I have aready opened the Window once - every time I open it again, its no problem anymore.(not rendering new .... ?)

我尝试过的事情:

  • Visibility设置为Hidden并等待(Thread.Sleep())10秒,然后设置Visibility = Visibility.Visible;
  • 将所有数据添加到ViewModel-Constructor中的DataGrid
  • Setting the Visibility to Hidden and wait(Thread.Sleep()) 10 secs then set Visibility = Visibility.Visible;
  • Adding all the Data into my DataGrid in ViewModel-Constructor

但是所有这些并没有真正解决它.我什至不确定是C#代码还是绑定...

but all this didn't really fix it. I ain't even sure if it's the C# Code or just the Bindings...

这可能是一个愚蠢的问题,但是有没有办法在显示DataGrid及其Content之前对其进行预渲染"?

This may be a silly question but is there a way to "pre-render" the DataGrid and its Content before displaying it ?

我还使用一些DataTriggers设置RowColor,但这可能不是问题.

I also use some DataTriggers to set RowColor but this might not be the problem..

以下是我使用的一些代码:

入门课程:

The Entry Class:

 public class LogEntry
{
    public string LogLevel { get; set; }
    public string LogLevelIcon
    {
        get
        {
            switch(LogLevel)
            {
                case "[D]":     //IF DEBUG ENTRY:
                    return "pack://application:,,,/Resources/Bug.png";
                case "[F]":     //IF FATAL ENTRY
                    return "pack://application:,,,/Resources/System-error-alt.png";
                case "[E]":     //IF ERROR ENTRY
                    return "pack://application:,,,/Resources/Error_32_WhiteBackground.png";
                case "[I]":     //IF INFO ENTRY
                    return "pack://application:,,,/Resources/Info_32.png";
                case "[W]":     //IF WARNING ENTRY
                    return "pack://application:,,,/Resources/Warning_32_WhiteBackground.png";
                case "[DB]":    //IF DB ENTRY
                    return "pack://application:,,,/Resources/Database.png";
                default:
                    return string.Empty;
            }                
        }
    }
    public string Message { get; set; }
    public DateTime DateTime { get; set; }

    public override string ToString()
    {
        return $"{LogLevel};{DateTime.ToString("dd.MM.yyyy HH:mm:ss")};{Message}";
    }
}

从我的LogFile获取数据:

Getting the Data from my LogFile:

public void ExtractDataFromLogFile(string logFilePath)
    {
        new Thread(() => {

            List<string> linesInFile = new List<string>();
            using (FileStream stream = File.Open(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    while (true)
                    {
                        while (!reader.EndOfStream)
                        {
                            ProcessFileContent(reader.ReadLine());
                        }
                        while (reader.EndOfStream)
                        {
                            Thread.Sleep(50);
                        }
                    }
                }
            }

        }).Start();
    }

添加到ObservableCollection<LogEntry>() _logEntries;:

private void ProcessFileContent(string line)
    {
        Match match = _regex.Match(line);
        if (match.Success)
        {
            LogEntry entry = new LogEntry()
            {
                LogLevel = match.Groups[1].ToString(),
                DateTime = DateTime.Parse(match.Groups[2].ToString(), new CultureInfo("de-DE")),
                Message = match.Groups[3].ToString()
            };                    
            _logEntries.Add(entry);                    
        }
    }

最后是DataGrid的XAML(样式遗漏了!):

Finally the XAML of the DataGrid (Styles left out!):

<DataGrid Grid.Row="1"
          x:Name="DataGrid"
          Grid.ColumnSpan="2"
          Margin="5"
          IsReadOnly="True"
          AutoGenerateColumns="False"
          CanUserReorderColumns="False"
          ItemsSource="{Binding Path=ItemsView, UpdateSourceTrigger=PropertyChanged}">
  <DataGrid.Columns>
            <DataGridTemplateColumn Width="Auto">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="{Binding Path=LogLevelIcon, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                               Width="16" 
                               Height="16"></Image>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Width="Auto" Header="Datum"
                                Binding="{Binding Path=DateTime, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>               
            <DataGridTextColumn Width="*" Header="Meldung"
                                Binding="{Binding Path=Message, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
        </DataGrid.Columns>
    </DataGrid>

请注意,"ItemsView"的类型为ICollectionView

Note that "ItemsView" is typeof ICollectionView

我在这里填写

private void InitializeCollection()
    {
        ItemsView = CollectionViewSource.GetDefaultView(_logEntries);
        BindingOperations.EnableCollectionSynchronization(_logEntries, _lock);
    }

推荐答案

从文件中读取后,您应更改为:

With reading from file, you should change to:

XAML:

<DataGrid
          Grid.Row="1"
      x:Name="DataGrid"
      Grid.ColumnSpan="2"
      Margin="5"
      IsReadOnly="True"
      AutoGenerateColumns="False"
      CanUserReorderColumns="False" ItemsSource="{Binding}">
    <DataGrid.Columns>
        <DataGridTemplateColumn Width="Auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image Source="{Binding Path=LogLevelIcon, Mode=OneWay}" Width="16" Height="16"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Width="Auto" Header="Datum" Binding="{Binding Path=DateTime, Mode=OneWay}"/>
        <DataGridTextColumn Width="*" Header="Meldung" Binding="{Binding Path=Message, Mode=OneWay}"/>
    </DataGrid.Columns>
</DataGrid>

C#代码:

Dispatcher DP = Dispatcher.CurrentDispatcher;

public void ExtractDataFromLogFile(string logFilePath)
{
    new Thread(() =>
    {
        var lines = File.ReadAllLines(logFilePath);
        foreach (var line in lines) ProcessFileContent(line);
        DP.Invoke(() => DataGrid.DataContext = _logEntries);
    }).Start();
}

private void ProcessFileContent(string line)
{
    Match match = _regex.Match(line);
    if (match.Success)
    {
        LogEntry entry = new LogEntry()
        {
            LogLevel = match.Groups[1].ToString(),
            DateTime = DateTime.Parse(match.Groups[2].ToString(), new CultureInfo("de-DE")),
            Message = match.Groups[3].ToString()
        };
        _logEntries.Add(entry);
    }
}

如果您对_logEntries有任何绑定,请立即将其删除.

If you have any binding to _logEntries, remove it by now.

按以下方式调用它:

ExtractDataFromLogFile("yourLogFile");

这会将您的数据加载到_logEntries,完成后会自动绑定到DataGrid.

This will load your data to _logEntries, after finish, it auto bind to DataGrid.

这篇关于TextFile的Lifeupdate DataGrid具有良好的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆