使用C#和WPF制作终端的控件是什么

我正在开发一个发送命令和数据,接收日志和数据等的终端软件……

端子S / W通过USB接口与Arm Cortex通信.

为了开发,我使用C#和WPF文本框作为终端屏幕.
但是,我遇到了一些问题.

与USB接口相比,更新文本框的速度非常慢.

我怎么解决这个问题?

如果你有解决方案或知道WPF为终端做的用户控制.

请告诉我.

谢谢.

其他信息.

1.string属性,用于绑定到TextBox

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

2.test用于更新日志的功能

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.性能分析仪的结果导致VS2012
《使用C#和WPF制作终端的控件是什么》

最佳答案 StringBuilder可能不是这里的方法,通常在循环或其他进程中附加大量数据时使用,并希望在最后调用ToString.在这种情况下,性能比通过内存分配开销做一堆显式字符串连接更好.

我不完全确定你的应用程序,但我猜你只想显示终端的一些输出.我建议你将文本行存储在ObservableCollection属性中,并在收到新行时添加到它.我做了类似的事情,并有一个扩展的RichTextBox与DataSource属性,我用来显示行.我确信有更快的方法可以做到这一点(RichTextBox因其性能而闻名,我每次添加一行时都会构建一个新的内联块),但我从未注意到任何性能问题 – 并且它允许我可以根据事件类型等格式化颜色编码.

无论如何,我已尽力复制我所拥有的内容,同时删除了我的具体实现细节,我没有特别测试.

EventLogBox类:

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;
                }
        }
    }
}

ViewModel中的属性

private ObservableCollection<string> mLines = new ObservableCollection<string>();

public ObservableCollection<string> Lines
{
    get
    {
        return mLines;
    }
}

在XAML中:

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

然后,当您从终端收到新线路时,请致电

Lines.Add(newLine);
点赞