What controls are used to create a terminal using C # and WPF

I develop software for terminals that send command and data, get log and data, etc.

The S / W terminal communicates with Arm Cortex via a USB interface.

For development, I used the C # and WPF text boxes for the terminal screen. But I ran into some problems.

Updating the text box is very slow compared to the USB interface.

How can I solve this problem?

If you have solutions or know usercontrol made by WPF for the terminal.

Please let me know.

Thanks.

Additional Information.

1.string property for binding to TextBox

public string TestString { get { return _testString; } set { _testString = value; RaisePropertyChangedEvent("TestString"); } } 

2.test functions for updating the log

 StringBuilder testBulider = new StringBuilder(); testBulider.Capacity = 1000000; for (int i = 0; i < 1000; ++i) { testBulider.Append(i.ToString("x4") + "\n"); testString = testBulider.ToString(); // Very Slow Point } 

3. Capturing performance analyzer leads to VS2012 enter image description here

+4
source share
1 answer

StringBuilder may not be here, and is usually used when you add a lot of data to a loop or another process and want to call ToString at the very end. Performance in this case is better than, say, performing a bunch of explicit string concatenations due to memory overhead.

I'm not quite sure about your application, but I think you just want to display some output from the terminal. I suggest you save the lines of text in the ObservableCollection property and add to it when you get new lines. I am doing something similar and have an extended RichTextBox with a DataSource property that I use to display rows. I'm sure there are faster ways to do this (RichTextBox is NOT known for its performance, and I build a new inline block every time a line is added), but I never noticed any performance issues - and this allowed me to get creative with color encoding formatted based on event type, etc.

In any case, I did my best to copy what I have, while I remove the details of my specific implementation, I did not test it specifically.

EventLogBox Class:

 public class EventLogBox : RichTextBox { public EventLogBox() { } static EventLogBox() { RichTextBox.IsReadOnlyProperty.OverrideMetadata( typeof(EventLogBox), new FrameworkPropertyMetadata(true)); RichTextBox.VerticalScrollBarVisibilityProperty.OverrideMetadata( typeof(EventLogBox), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible)); RichTextBox.FontFamilyProperty.OverrideMetadata( typeof(EventLogBox), new FrameworkPropertyMetadata(new FontFamily("Courier New"))); } private void AddItem(string pEntry) { Paragraph a = new Paragraph(); Run messageRun = new Run(pEntry); a.Inlines.Add(messageRun); this.Document.Blocks.Add(a); this.ScrollToEnd(); } private void LoadNewItems() { this.Document.Blocks.Clear(); foreach (string entry in DataSource) { this.AddItem(entry); } } /// <summary> /// The source of content (EventLogEntrys) /// </summary> public IEnumerable<string> DataSource { get { return (IEnumerable<string>)GetValue(DataSourceProperty); } set { SetValue(DataSourceProperty, value); } } /// <summary> /// Using a DependencyProperty as the backing store for <see cref="DataSource"/>. /// This enables animation, styling, binding, etc... /// </summary> public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register ( "DataSource", typeof(IEnumerable<string>), typeof(EventLogBox), new PropertyMetadata ( new ObservableQueue<string>(), new PropertyChangedCallback(DataSourcePropertyChanged) ), new ValidateValueCallback(IsValidDataSourceProperty) ); /// <summary> /// We also ned to impliment the INotifyCollectionChanged interface /// in order for everything to work properly. /// </summary> /// <param name="pValue"></param> /// <returns></returns> private static bool IsValidDataSourceProperty(object pValue) { return pValue is INotifyCollectionChanged; } /// <summary> /// Callback when the DataSourceProperty changes. Setup the new /// CollectionChanged events, etc. /// </summary> /// <param name="pSender"></param> /// <param name="pArgs"></param> private static void DataSourcePropertyChanged(DependencyObject pSender, DependencyPropertyChangedEventArgs pArgs) { EventLogBox s = ((EventLogBox)pSender); ((INotifyCollectionChanged)s.DataSource).CollectionChanged -= new NotifyCollectionChangedEventHandler( s.DataSource_CollectionChanged); ((INotifyCollectionChanged)s.DataSource).CollectionChanged += new NotifyCollectionChangedEventHandler( s.DataSource_CollectionChanged); s.LoadNewItems(); } /// <summary> /// /// </summary> /// <param name="pSender"></param> /// <param name="pArgs"></param> private void DataSource_CollectionChanged(object pSender, NotifyCollectionChangedEventArgs pArgs) { IList n = pArgs.NewItems; switch (pArgs.Action) { case NotifyCollectionChangedAction.Add: { foreach (string cle in pArgs.NewItems) { AddItem(cle); } break; } case NotifyCollectionChangedAction.Remove: { for (int i = pArgs.OldStartingIndex; i < pArgs.OldItems.Count; i++) { this.Document.Blocks.Remove(this.Document.Blocks.ElementAt(i)); } break; } case NotifyCollectionChangedAction.Replace: { break; } } } } 

Property in ViewModel

 private ObservableCollection<string> mLines = new ObservableCollection<string>(); public ObservableCollection<string> Lines { get { return mLines; } } 

In XAML:

 <local:EventLogBox DataSource="{Binding Path=Lines}" Height="100"/> 

Then, when you get a new line from your terminal, call

 Lines.Add(newLine); 
+2
source

All Articles