【问题标题】:Change foreground color of selected text in RichTextBox from context menu从上下文菜单更改 RichTextBox 中选定文本的前景色
【发布时间】:2018-08-01 19:07:50
【问题描述】:

我的应用程序具有带有自定义上下文菜单的 RichTextBox。我可以使用 TextBoxSelectionHelper 附加属性获取选定的文本,但是当用户单击“问题”菜单项时,我无法设置该选定文本的前景色(红色或绿色)。以下是我迄今为止在这方面的工作,我遵循 MVVM 模式。

<RichTextBox Margin="50" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                ScrollViewer.CanContentScroll="True"
                ScrollViewer.VerticalScrollBarVisibility="Visible"
                AcceptsReturn="True"
                VerticalScrollBarVisibility="Auto"
                utils:TextBoxSelectionHelper.SelectedText="{Binding Selectedknowlwdge,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <FlowDocument>
                <Paragraph>
                    <Run Text="{Binding KnowledgeText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                </Paragraph>
            </FlowDocument>
            <RichTextBox.ContextMenu>
        <ContextMenu>
            <MenuItem Command="{Binding MarkQuestion}" Header="_Question">
                <MenuItem.Icon>
                    <materialDesign:PackIcon  Kind="CommentQuestionOutline" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Command="{Binding MarkQuestion}" Header="_Answer">
                <MenuItem.Icon>
                    <materialDesign:PackIcon  Kind="LightbulbOnOutline" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Command="{Binding MarkQuestion}" Header="_Clear">
                <MenuItem.Icon>
                    <materialDesign:PackIcon  Kind="FormatClear" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Command="Cut" Header="_Cut">
                <MenuItem.Icon>
                    <materialDesign:PackIcon  Kind="ContentCut" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Command="Copy" Header="_Copy">
                <MenuItem.Icon>
                    <materialDesign:PackIcon  Kind="ContentCopy" />
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Command="Paste" Header="_Paste">
                <MenuItem.Icon>
                    <materialDesign:PackIcon  Kind="ContentPaste" />
                </MenuItem.Icon>
            </MenuItem>
        </ContextMenu>
    </RichTextBox.ContextMenu>
</RichTextBox>




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace Test.Utils
{
    public class TextBoxSelectionHelper
    {
        public static string GetSelectedText(DependencyObject obj)
        {
            return (string)obj.GetValue(SelectedTextProperty);
        }

        public static void SetSelectedText(DependencyObject obj, string value)
        {
            obj.SetValue(SelectedTextProperty, value);

        }

        // Using a DependencyProperty as the backing store for SelectedText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedTextProperty =
            DependencyProperty.RegisterAttached(
                "SelectedText",
                typeof(string),
                typeof(TextBoxSelectionHelper),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, SelectedTextChanged));

        private static void SelectedTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            RichTextBox tb = obj as RichTextBox;
            if (tb != null)
            {
                if (e.OldValue == null && e.NewValue != null)
                {
                    tb.SelectionChanged += tb_SelectionChanged;
                }
                else if (e.OldValue != null && e.NewValue == null)
                {
                    tb.SelectionChanged -= tb_SelectionChanged;
                }

                string newValue = e.NewValue as string;

                if (newValue != null && newValue != tb.Selection.Text)
                {
                    tb.Selection.Text = newValue as string;


                }
            }
        }

        static void tb_SelectionChanged(object sender, RoutedEventArgs e)
        {
            RichTextBox tb = sender as RichTextBox;
            if (tb != null)
            {
                SetSelectedText(tb, tb.Selection.Text);
            }
        }
    }
}



public ICommand MarkQuestion
{
    get { return new RelayCommand(param => QuestionMarker()); }
}

void QuestionMarker()
{
    //here it should change foreground color of selected text to RED.
}



private string _SelectedText="";
public string Selectedknowlwdge
{
    get { return _SelectedText; }
    set
    {
    _SelectedText = value;
    OnPropertyChanged();
    }
}

private string _KnowledgeText="";
public string KnowledgeText
{
    get { return _KnowledgeText; }
    set
    {
    _KnowledgeText = value;
    OnPropertyChanged();
    }
}

【问题讨论】:

    标签: c# wpf xaml richtextbox attached-properties


    【解决方案1】:

    RichTextBox 不支持数据绑定,因此您需要推出自己的解决方案(这不是一件小事)或使用开箱即用的解决方案,例如 the one from the WPF Toolkit

    【讨论】:

    • 绑定不是问题,我可以使用此代码进行绑定。
    • 我想这完全取决于你想要做什么。如果您想完全控制一切,那么您将需要通过数据绑定来控制实际的文档元素。如果这真的只是设置选择文本样式的情况,那么我认为您可能会通过设置SelectionBrush 属性并将IsInactiveSelectionHighlightEnabled 设置为true?我认为这只是设置背景,这就是为什么我怀疑你必须走完整的数据绑定路线。
    猜你喜欢
    • 2020-09-06
    • 2011-04-27
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    相关资源
    最近更新 更多