【问题标题】:Making specific part of Text bold in RichTextBox in a DataGrid using WPF使用 WPF 在 DataGrid 中的 RichTextBox 中将文本的特定部分加粗
【发布时间】:2021-09-30 12:33:42
【问题描述】:

我正在制作一个 C# WPF 应用程序,目前有一个 DataGrid,其中包含各种元素,包括 RichTextBox,以便用户可以编辑文本。但是,我还想提供将 RichTextBox 中包含的文本的特定部分设为粗体的选项。这应该通过在 TextBox 中选择部分文本并按下按钮来完成,这将使所选文本变为粗体。

So the highlighted "Lorem ipsum dolor sit amet" would be made bold when the button is pressed.

我的 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>

我没有包括每一列,但它应该能让我了解我正在处理的内容。

到目前为止,我已经设法获得突出显示的文本。然后我尝试在所选文本周围添加各种粗体标签,但是这些标签只显示在文本框中。

【问题讨论】:

标签: c# wpf datagrid format richtextbox


【解决方案1】:

但是,我还想提供将 RichTextBox 中包含的文本的特定部分设为粗体的选项。这应该通过在 TextBox 中选择部分文本并按下按钮来完成,这将使所选文本变为粗体

有几种方法可以实现。目前看来您正在使用绑定关注mvvm,这是使用wpf 时的首选方式。考虑到这一点,您可以创建一个继承 RichTextBox 的新类并实现您需要的行为。

这是一个满足您需要的示例类:

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);
        }
    }
}

重新编译后,您可以将其添加为该列的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>

您会注意到一个依赖属性:DoBoldSelection。此属性处理更改选定文本的字体粗细。在上面的示例中,该属性绑定到我的List&lt;DescriptionObject&gt; 中的一个属性,即AllowBoldHighlight

我的DescriptionObject 类看起来像:

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 看起来像:

<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 看起来像:

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;
            }
        }

    }

您会注意到在Button_Click 中您可以处理更改所选文本的FontWeight;基本示例。主要驱动力是dobj.AllowBoldHighlight = true。发生的情况是,当您选择/突出显示文本然后单击按钮时,dobj.AllowBoldHighlight 属性会发生更改,该更改会触发RichTextSelection 类中的OnBoldSelectionChanged。上面的示例使您可以灵活地在网格中的每个对象/实例上关闭和打开它。

这是它工作的一个短片:

希望这能帮助并解决您的问题,如果有任何问题,请告诉我。

【讨论】:

  • 感谢您提供非常详细的回答。这绝对解决了在 RichTextBox 中格式化粗体文本的问题。然而,有了这个解决方案,我遇到了一个新问题。如果字符串的一部分被加粗,那么当我稍后尝试从对象中获取字符串时,它的一部分就丢失了。所以如果我有字符串“一二三四”,我把“三”加粗。然后,当尝试获取字符串时,我只会得到“一二”。现在我的解决方案是存储来自 SelectionChanged 的​​ TextRange,然后使用 ApplyPropertyValue,然后从局部变量中用自身覆盖字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-24
  • 2015-12-01
相关资源
最近更新 更多