【问题标题】:Why isnt my RichTextBox not changing foreground color databinding为什么我的 RichTextBox 没有更改前景色数据绑定
【发布时间】:2018-05-10 04:44:20
【问题描述】:

所以我目前正在尝试将消息从进程打印到富文本框,除了我希望它以红色文本显示错误消息和以绿色显示正常消息之外,一切都很好。

由于某种原因,它都是绿色的,我认为这是因为我正在绑定前景而不是附加到 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();
    }

服务器.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>

【问题讨论】:

    标签: c# .net xaml mvvm data-binding


    【解决方案1】:

    是的,我认为您是对的:Foreground 属性指的是RichTextBox 中的所有文本,而不是单个项目。

    我可以建议您的问题的解决方案,但请耐心等待......

    单独收集消息

    当我说“消息”时,我的意思是传递给 OKDataReceivedErrorDataReceived 的任何内容。

    您的架构中存在一个问题,即您无法区分流程中的“好”消息和“坏”消息。 OutputStream 包含两者,当MessageColor 更改时,它会更改所有以前的消息,而不仅仅是最新消息。

    我建议更改创建一个 Message 类,其中包含消息文本和一个标志,以判断它是“好”消息还是“坏”消息。当您从流程中获取新数据时,您会创建 Message 并相应地设置“好”或“坏”标志。

    然后将OutputStream 替换为ObservableCollection&lt;Message&gt; 类型的属性。从进程创建新的Message 后,您可以将其添加到此ObservableCollection&lt;Message&gt;。这是最终将绑定到您的视图的属性。请注意,当向ObservableCollection 添加新项目时,它会自动刷新绑定。

    现在,我没有忘记您关于如何在视图上以不同颜色显示文本的原始问题。我可以给你一个建议,但这取决于模型中有ObservableCollection&lt;Message&gt;

    将消息转换为 FlowDocument

    ObservableCollection&lt;Message&gt; 绑定到RichTextBox 控件,但使用IValueConverter 将所有Messages 转换为FlowDocument。每条消息都将转换为 ParagraphRun,其中包含文本。然后将段落上的Foreground 属性设置为Message 中标志的正确颜色。您还需要将该属性绑定到RichTextBox.Document 属性。 RichTextBox 的 MSDN 文章有一个很好的小例子,我想你可以从那里弄清楚。

    这种方法的主要缺点是,每当进程发出新消息时,都需要将整个ObservableCollection 再次转换为FlowDocument,而不仅仅是新项目。但我认为这对性能的影响是微乎其微的。

    我认为这将是最好的方法。最后,您将拥有一个带有可区分消息的视图模型、一个可以根据需要进行修改的转换器,并且只对视图本身进行一些更改。

    【讨论】:

    • 我喜欢这样!我以前玩过 ObservableCollections 但是哇,这将是一个挑战!我将立即开始工作,并希望它能够发挥作用,我真的很喜欢创建一个区分“好”和“坏”消息的类的想法。
    猜你喜欢
    • 2020-10-13
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多