Implémentation d’un visualiseur de journaux avec WPF

Je recherche des conseils pour la meilleure approche pour implémenter un visualiseur de consoles de consignation avec WPF.

Il doit correspondre aux critères suivants:

  • défilement rapide avec plus de 100 000 lignes
  • Certaines entrées (comme les stacktraces) doivent être pliables
  • objects longs
  • la liste peut être filtrée par différents critères (recherche, tags, etc.)
  • à la fin, il devrait continuer à défiler lorsque de nouveaux éléments sont ajoutés
  • Les éléments de ligne peuvent contenir une sorte de formatage supplémentaire comme les liens hypertexte et le compteur d’occurrences

En général, j’ai en tête quelque chose comme la fenêtre de console de FireBug et Chrome.

J’ai joué avec cela, mais je n’ai pas beaucoup progressé, car … – la grid de données ne peut pas gérer différentes hauteurs d’élément – la position de défilement n’est mise à jour qu’après avoir libéré la barre de défilement (ce qui est totalement inacceptable).

Je suis certain que j’ai besoin d’une forme de virtualisation et que j’adorerais suivre le modèle MVVM.

Toute aide ou pointeur sont les bienvenus.

Je devrais commencer à vendre ces échantillons WPF au lieu de les dissortingbuer gratuitement. = P

entrer la description de l'image ici

  • Interface utilisateur VirtualizingStackPanel (utilisant VirtualizingStackPanel ) qui fournit des performances incroyablement bonnes (même avec plus de 200 000 éléments)
  • Entièrement compatible MVVM.
  • DataTemplate s pour chaque type de type LogEntry . Celles-ci vous permettent de personnaliser autant que vous le souhaitez. Je n’ai implémenté que deux types de LogEnsortinges (basiques et nesteds), mais vous avez l’idée. Vous pouvez sous- LogEntry autant que vous en avez besoin. Vous pouvez même prendre en charge du texte ou des images riches.
  • Éléments extensibles (nesteds).
  • Word Wrap.
  • Vous pouvez implémenter le filtrage, etc. en utilisant un CollectionView .
  • WPF Rocks, il suffit de copier et coller mon code dans un File -> New -> WPF Application et voir les résultats pour vous-même.

                                                               

Code Behind: (Notez que la majeure partie est juste boileplate pour supporter l’exemple (générer des entrées aléatoires)

  public partial class LogViewer : Window { private ssortingng TestData = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"; private List words; private int maxword; private int index; public ObservableCollection LogEnsortinges { get; set; } public LogViewer() { InitializeComponent(); random = new Random(); words = TestData.Split(' ').ToList(); maxword = words.Count - 1; DataContext = LogEnsortinges = new ObservableCollection(); Enumerable.Range(0, 200000) .ToList() .ForEach(x => LogEnsortinges.Add(GetRandomEntry())); Timer = new Timer(x => AddRandomEntry(), null, 1000, 10); } private System.Threading.Timer Timer; private System.Random random; private void AddRandomEntry() { Dispatcher.BeginInvoke((Action) (() => LogEnsortinges.Add(GetRandomEntry()))); } private LogEntry GetRandomEntry() { if (random.Next(1,10) > 1) { return new LogEntry() { Index = index++, DateTime = DateTime.Now, Message = ssortingng.Join(" ", Enumerable.Range(5, random.Next(10, 50)) .Select(x => words[random.Next(0, maxword)])), }; } return new CollapsibleLogEntry() { Index = index++, DateTime = DateTime.Now, Message = ssortingng.Join(" ", Enumerable.Range(5, random.Next(10, 50)) .Select(x => words[random.Next(0, maxword)])), Contents = Enumerable.Range(5, random.Next(5, 10)) .Select(i => GetRandomEntry()) .ToList() }; } } 

Éléments de données:

 public class LogEntry: PropertyChangedBase { public DateTime DateTime { get; set; } public int Index { get; set; } public ssortingng Message { get; set; } } public class CollapsibleLogEntry: LogEntry { public List Contents { get; set; } } 

PropertyChangedBase:

  public class PropertyChangedBase:INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(ssortingng propertyName) { Application.Current.Dispatcher.BeginInvoke((Action) (() => { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); })); } } 

La réponse de HighCore est parfaite, mais je suppose que cette exigence manque: “à la fin, il faut continuer à faire défiler lorsque de nouveaux éléments sont ajoutés”.

Selon cette réponse, vous pouvez le faire:

Dans le ScrollViewer principal (à l’intérieur du DockPanel), ajoutez l’événement:

  

Lancez la source d’événement pour faire le défilement automatique:

  private bool AutoScroll = true; private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { // User scroll event : set or unset autoscroll mode if (e.ExtentHeightChange == 0) { // Content unchanged : user scroll event if ((e.Source as ScrollViewer).VerticalOffset == (e.Source as ScrollViewer).ScrollableHeight) { // Scroll bar is in bottom // Set autoscroll mode AutoScroll = true; } else { // Scroll bar isn't in bottom // Unset autoscroll mode AutoScroll = false; } } // Content scroll event : autoscroll eventually if (AutoScroll && e.ExtentHeightChange != 0) { // Content changed and autoscroll mode set // Autoscroll (e.Source as ScrollViewer).ScrollToVerticalOffset((e.Source as ScrollViewer).ExtentHeight); } } }