как динамически добавлять содержимое в поле расширенного текста в приложении wpf, используя xaml - PullRequest
0 голосов
/ 11 октября 2019

Я разрабатываю графический интерфейс, где пользователь может подключиться к серверу и читать данные. Данные должны отображаться в графическом интерфейсе. Для этого я использую TabControl, чье ContentTemplate установлено в RichTextBox. Код XAML выглядит следующим образом:

<TabControl x:Name="tabControl1" HorizontalAlignment="Stretch" MinHeight="50" Margin="0,0,0,0.2" Width="884"
                            ItemsSource="{Binding Titles, Mode=TwoWay}" Height="454" VerticalAlignment="Bottom">
                    <TabControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Header}"/>
                        </DataTemplate>
                    </TabControl.ItemTemplate>
                    <TabControl.ContentTemplate>
                        <DataTemplate>
                            <RichTextBox Margin="10" VerticalScrollBarVisibility="Visible" >
                                <FlowDocument>
                                    <Paragraph FontSize="12" FontFamily="Courier New">
                                        <Run Text="{Binding Content}"></Run>
                                    </Paragraph>
                                </FlowDocument>
                            </RichTextBox>
                        </DataTemplate>
                    </TabControl.ContentTemplate>
</TabControl>

Фоновый код для добавления новой вкладки и установки ее заголовка / содержимого (статический) ниже

    public class MainWindowVM : INotifyPropertyChanged
    {
        public MainWindowVM()
        {
            Titles = new ObservableCollection<Item>();
        }

        public class Item
        {
            public string Header { get; set; }
            public string Content { get; set; }
        }
        public ObservableCollection<Item> Titles
        {
            get { return _titles; }
            set
            {
                _titles = value;
                OnPropertyChanged("Titles");
            }
        }

        static int tabs = 1;
        private ObservableCollection<Item> _titles;
        private ICommand _addTab;
        private ICommand _removeTab;

        public ICommand AddTab
        {
            get
            {
                 _addTab = new TabRelayCommand(
                    x =>
                    {
                        AddTabItem();
                    });
                return _addTab;
            }
        }
        public ICommand RemoveTab
        {
            get
            {
                _removeTab = new TabRelayCommand(
                    x =>
                    {
                        RemoveTabItem();
                    });
                return _removeTab;
            }
        }
        private void RemoveTabItem()
        {
            if (Titles.Count > 0)
            {
                Titles.Remove(Titles.Last());
                tabs--;
            }
        }

        public Item AddTabItem()
        {
            var header = "Log_" + tabs;
            var content = "Content " + tabs;
            var item = new Item { Header = header, Content = content };
            Titles.Add(item);
            tabs++;
            OnPropertyChanged("Titles");
            return item;
        }

        public void AddTabItem(string strFileName, string strContent)
        {
            var header = strFileName;
            var content = strContent;
            var item = new Item { Header = header, Content = content };
            Titles.Add(item);
            tabs++;
            OnPropertyChanged("Titles");
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }

Однако мне нужно установить содержимоезаголовок динамически (данные читаются из сокета). Я могу прочитать данные, которые у меня есть в формате строки. Пожалуйста, предложите мне, как мне установить содержимое RichTextBox, добавив строку. Я новичок в C #. Заранее спасибо

Редактировать : после нажатия кнопки мое приложение подключается к серверу. Также я запускаю параллельное задание, которое читает данные из сокета.

Проблема: Слишком много процессорного времени занято (я вижу до 80 в разделе Процессы в диспетчере задач).

 private void BtnConnect_Click(object sender, RoutedEventArgs e)
        {
            //connect
            TCPClientClass tcpClient = TCPConnHandler.ConnectToService(tbIPAddress.Text);
            if (tcpClient != null)
            {
                MessageBox.Show("Connected to " + tbIPAddress.Text);
                //open new tab
                var item = MainWindowVMObj.AddTabItem();


                //now run a task to display the data in the tab
                Thread thTabControl = new Thread(() =>
                {
                    while (tcpClient.Connected)
                    {
                        String str = tcpClient.GetDataFromServer();
                        if (!String.IsNullOrEmpty(str))
                            tabControl1.Dispatcher.BeginInvoke((Action)(() => item.Content += str));
                        Thread.Sleep(200);
                    }
                    //item.Dispatcher.BeginInvoke
                });

                thTabControl.Start();
            }

        }

1 Ответ

1 голос
/ 11 октября 2019

Вы можете найти Item для обновления в Titles и установить его свойство Content.

Например, это устанавливает свойство первого элемента (индекс 0) в ObservableCollection<Item>:

Titles[0].Content += "append...";

Класс Item также должен реализовывать INotifyPropertyChanged, чтобы вы моглисмотрите изменения без переключения вкладок:

public class Item : INotifyPropertyChanged
{
    public string Header { get; set; }

    private string _content;
    public string Content
    {
        get { return _content; }
        set { _content = value; OnPropertyChanged(nameof(Content)); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
...