简体   繁体   English

使用 WPF 在 DataGrid 的 RichTextBox 中使文本的特定部分加粗

[英]Making specific part of Text bold in RichTextBox in a DataGrid using WPF

I'm making a C# WPF application and currently have a DataGrid that contains various elements including a RichTextBox so that users can edit the text.我正在制作一个 C# WPF 应用程序,目前有一个 DataGrid,其中包含各种元素,包括 RichTextBox,以便用户可以编辑文本。 However I would like to also give the option of making specific parts of the Text contained in the RichTextBox bold.但是,我还想提供将 RichTextBox 中包含的文本的特定部分设为粗体的选项。 This should be done by selecting part of the Text in a TextBox and pressing a button, that would make the selected text bold.这应该通过选择 TextBox 中的部分文本并按下按钮来完成,这将使所选文本变为粗体。

So the highlighted "Lorem ipsum dolor sit amet" would be made bold when the button is pressed.因此,当按下按钮时,突出显示的“Lorem ipsum dolor sit amet”将变为粗体。

My XAML is setup like this:我的 XAML 是这样设置的:

<DataGrid Grid.Row="1" AutoGenerateColumns="False" Name="DescriptionGrid"
      RowHeaderWidth="15"
      ItemsSource="{Binding Descriptions}"
      VirtualizingPanel.IsVirtualizing="False">
<DataGrid.Columns>
    <DataGridTemplateColumn Header="Description" Width="300">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <RichTextBox Width="Auto" AcceptsReturn="True">
                    <FlowDocument>
                        <Paragraph>
                            <Run Text="{Binding desc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Paragraph>
                    </FlowDocument>
                </RichTextBox>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

I have not included every column, but it should give a understanding of what I'm working with.我没有包括每一列,但它应该让我了解我正在处理的内容。

So far I've managed to get the highlighted text.到目前为止,我已经设法获得突出显示的文本。 I then tried to add various bold tags around the selected text, however these tags just show up in the textbox.然后我尝试在所选文本周围添加各种粗体标记,但是这些标记只显示在文本框中。

However I would like to also give the option of making specific parts of the Text contained in the RichTextBox bold.但是,我还想提供将 RichTextBox 中包含的文本的特定部分设为粗体的选项。 This should be done by selecting part of the Text in a TextBox and pressing a button, that would make the selected text bold这应该通过选择 TextBox 中的部分文本并按下按钮来完成,这将使所选文本变为粗体

There are a few ways this can be accomplished.有几种方法可以实现这一点。 Currently it appears you are following mvvm with binding, this is the preferred way when working with wpf .目前看来您正在使用带绑定的mvvm ,这是使用wpf时的首选方式。 With this in mind, you could create a new class that inherits the RichTextBox and implement the behavior you are needing.考虑到这一点,您可以创建一个新的 class 来继承RichTextBox并实现您需要的行为。

Here's an example class that does just what you need:这是一个示例 class,它可以满足您的需要:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace ChangeFontSelectionGridWPF
{
    public class RichTextSelection : RichTextBox
    {
        public static readonly DependencyProperty DoBoldSelectionProperty = DependencyProperty.Register(
                                                                                                    "DoBoldSelection", typeof(bool),
                                                                                                    typeof(RichTextSelection),
                                                                                                    new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnBoldSelectionChanged))
                                                                                                    );

        public bool DoBoldSelection
        {
            get => (bool)GetValue(DoBoldSelectionProperty);
            set => SetValue(DoBoldSelectionProperty, value);
        }

        public RichTextSelection()
            : base()
        {
        }

        private static void OnBoldSelectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextSelection rchTextSel = (RichTextSelection)d;
            if (rchTextSel.Selection != null)
                rchTextSel.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
        }
    }
}

After you recompile, you then can add this as your DataTemplate for that column, something like:重新编译后,您可以将其添加为该列的DataTemplate ,例如:

<DataTemplate>
             <local:RichTextSelection Width="Auto"
                 AcceptsReturn="True"
                 DoBoldSelection="{Binding AllowBoldHighlight}"
                                                     >
                                <FlowDocument>
                                    <Paragraph>
                                        <Run Text="{Binding desc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                    </Paragraph>
                                </FlowDocument>
                            </local:RichTextSelection>
                        </DataTemplate>

You'll notice a dependency property: DoBoldSelection .您会注意到一个依赖属性: DoBoldSelection This property handles changing the font weight of the selected text.此属性处理更改所选文本的字体粗细。 In the example above, that property is bound to a property in my List<DescriptionObject> which is AllowBoldHighlight .在上面的示例中,该属性绑定到我的List<DescriptionObject>中的一个属性,即AllowBoldHighlight

My DescriptionObject class looks like:我的DescriptionObject class 看起来像:

public class DescriptionObject : INotifyPropertyChanged
    {
        public string desc { get; set; } = string.Empty;

        private bool allowHighlight = false;
        public bool AllowBoldHighlight
        {
            get => allowHighlight;
            set => SetProperty(ref allowHighlight, value);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
            storage = value;
            OnPropertyChanged(propName);
            return true;
        }

    }

MainWindow.xaml looks like: MainWindow.xaml看起来像:

<Window x:Class="ChangeFontSelectionGridWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:ChangeFontSelectionGridWPF"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="800"
        Height="450"
        mc:Ignorable="d"
        >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Button Grid.Row="0"
                Grid.Column="1"
                Margin="10"
                Click="Button_Click"
                Content="Bold"
                />
        <DataGrid x:Name="DescriptionGrid"
                  Grid.Row="1"
                  Grid.ColumnSpan="2"
                  AutoGenerateColumns="False"
                  ItemsSource="{Binding Descriptions}"
                  >
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="300" Header="Description">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <local:RichTextSelection Width="Auto"
                                                     AcceptsReturn="True"
                                                     DoBoldSelection="{Binding AllowBoldHighlight}"
                                                     >
                                <FlowDocument>
                                    <Paragraph>
                                        <Run Text="{Binding desc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                    </Paragraph>
                                </FlowDocument>
                            </local:RichTextSelection>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>

MainWindow.cs looks like: MainWindow.cs看起来像:

public partial class MainWindow : Window
    {
        public List<DescriptionObject> Descriptions { get; set; } = new List<DescriptionObject>();

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Descriptions.Add(new DescriptionObject() { desc = "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?" });
            Descriptions.Add(new DescriptionObject() { desc = "rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?" });
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (DescriptionGrid.SelectedItem is DescriptionObject dobj)
            {
                dobj.AllowBoldHighlight = true;
                dobj.AllowBoldHighlight = false;
            }
        }

    }

You'll notice that in Button_Click is where you could handle changing the FontWeight of selected text;您会注意到,在Button_Click中,您可以处理更改所选文本的FontWeight basic example.基本示例。 The main driver for this is dobj.AllowBoldHighlight = true .这样做的主要驱动因素是dobj.AllowBoldHighlight = true What's happening is when you select/highlight text and then click on the button, dobj.AllowBoldHighlight property get's change which the fires off the OnBoldSelectionChanged in the RichTextSelection class. The example above gives you flexibility to turn it off and on per object/instance in your grid.发生的事情是当您选择/突出显示文本然后单击按钮时, dobj.AllowBoldHighlight属性会发生变化,这会触发RichTextSelection OnBoldSelectionChanged中的 OnBoldSelectionChanged。上面的示例使您可以灵活地关闭和打开每个对象/实例你的网格。

Here's a short clip of it working:这是它工作的一个简短片段:

在此处输入图像描述

Hopefully this helps and addresses your concern, if any issues please let me know.希望这有助于解决您的问题,如果有任何问题,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM