Почему мой RichTextBox не меняет привязку данных цвета переднего плана - PullRequest
0 голосов
/ 10 мая 2018

Итак, я сейчас пытаюсь распечатать сообщения из процесса в richtextbox, и все работает отлично, кроме того, что я хочу, чтобы сообщения об ошибках отображались красным шрифтом, а обычные сообщения зеленым.

По какой-то причине это все зеленое, и я предполагаю, что это потому, что я привязываю передний план, а не добавляю к RTB, но я не уверен.

Как правильно сделать так, чтобы сообщения об ошибках становились красными, а обычные сообщения становились зелеными.

MainWindow.cs

 public partial class MainWindow : Window
    {
        static Server server = new Server();
        private readonly Thread ConsoleThread = new Thread(() => { server.Start("Start.bat"); });

        public MainWindow()
        {
            InitializeComponent();
            DataContext = server;
        }

        private void ButtonStart(object sender, RoutedEventArgs e)
        {
            ConsoleThread.Start();
        }

        private void tbConsole_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            => tbConsole.ScrollToEnd();
    }

Server.cs

class Server : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private Process pServer = new Process();

        private Brush color;

        public Brush MessageColor
        {
            get { return color; }
            set
            {
                color = value;
                OnPropertyChanged("MessageColor");
            }
        }

        private string outStream;
        public string OutputStream
        {
            get { return outStream; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    outStream += value + Environment.NewLine;
                    OnPropertyChanged("OutputStream");
                }
            }
        }


        public void Start(string Path)
        {

            pServer.StartInfo.FileName = Path;
            pServer.StartInfo.UseShellExecute = false;
            pServer.StartInfo.RedirectStandardOutput = true;
            pServer.StartInfo.RedirectStandardError = true;


            pServer.OutputDataReceived += OKDataReceived;
            pServer.ErrorDataReceived += ErrorDataReceived;


            pServer.Start();

            pServer.BeginOutputReadLine();
            pServer.BeginErrorReadLine();
        }

        private void OKDataReceived(object sender, DataReceivedEventArgs e)
        {
            MessageColor = Brushes.Green;
            OutputStream = e.Data;
        }

        private void ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            MessageColor = Brushes.Red;
            OutputStream = e.Data;
        }

        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handle = PropertyChanged;
            if (handle != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

XAML

 <Grid>
        <Button Click="ButtonStart" Content="Start" Margin="325,63,353,319"/>
        <xctk:RichTextBox FontSize="5" Name="tbConsole" Margin="143,149,164,81" BorderBrush="Gray" Padding="10" ScrollViewer.VerticalScrollBarVisibility="Auto" Text="{Binding Path=OutputStream, Mode=TwoWay}" Foreground="{Binding Path=MessageColor}" />
    </Grid>

1 Ответ

0 голосов
/ 10 мая 2018

Да, я думаю, что вы правы: свойство Foreground относится ко всему тексту в RichTextBox, а не к отдельным элементам.

Я могу предложить решение вашего вопроса, но потерпите меня ...

Собирать сообщения индивидуально

Когда я говорю «сообщение», я имею в виду все, что передается OKDataReceived и ErrorDataReceived.

В вашей архитектуре есть проблема, заключающаяся в том, что вы не различаете «хорошие» сообщения и «плохие» сообщения от вашего процесса. OutputStream содержит оба, и когда MessageColor изменится, он изменится для всех предыдущих сообщений, а не только для самого последнего.

Я бы предложил изменить класс Message с текстом сообщения и флажком, будь то "хорошее" или "плохое" сообщение. Когда вы получаете новые данные из процесса, вы создаете Message и устанавливаете флаг «хорошо» или «плохо» соответственно.

Затем замените OutputStream свойством типа ObservableCollection<Message>. После создания нового Message из процесса вы можете добавить его к этому ObservableCollection<Message>. Это свойство, которое в конечном итоге будет привязано к вашему мнению. Обратите внимание, что когда новый элемент добавляется в ObservableCollection, он автоматически обновляет привязку.

Теперь я не забыл ваш первоначальный вопрос о том, как отображать текст в представлении разными цветами. Я могу дать вам совет, но это зависит от наличия ObservableCollection<Message> в модели.

Преобразование сообщений в FlowDocument

Свяжите ObservableCollection<Message> с элементом управления RichTextBox, но используйте IValueConverter для преобразования всех Messages в FlowDocument. Каждое сообщение будет преобразовано в Paragraph с Run, который будет содержать текст. Затем вы должны установить для свойства Foreground в абзаце правильный цвет для флага в Message. Вам также необходимо привязать свойство к свойству RichTextBox.Document. В статье MSDN для RichTextBox есть небольшой пример, который, я думаю, вы сможете оттуда выяснить.

Основным недостатком этого подхода является то, что всякий раз, когда процесс выдает новое сообщение, ему потребуется снова преобразовать ObservableCollection в FlowDocument, а не только в новый элемент. Но я думаю, что влияние на производительность будет минимальным.

Я думаю, что это был бы лучший подход. В конце у вас будет модель представления с различимыми сообщениями, конвертер, который может быть изменен при необходимости, и только несколько изменений в самом представлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...