Добавление пользовательских элементов управления в Richtextbox - PullRequest
0 голосов
/ 10 июня 2019

У меня есть Richtextbox, привязываемый через объект зависимости, требовалось иметь возможность вставлять некоторые пользовательские элементы управления в текст, поэтому я подумал, что мне нужен потоковый документ, связанный с Richtextbox. Я попытался использовать набор инструментов xceed, но при использовании средства форматирования xaml создавался просто раздел вместо полного FlowDocument, который не работал нормально при добавлении элементов управления.

Все было хорошо, пока я не попытался загрузить xaml из базы данных. Ошибка в том, что свойство name было найдено несколько раз, что, как я понял, действительно правильно, поскольку xaml не допускает использование нескольких элементов управления с одним и тем же именем.

Richtextboxhelper

public class RichTextBoxHelper : DependencyObject
    {
        private static HashSet<Thread> _recursionProtection = new HashSet<Thread>();

        public static string GetDocumentXaml(DependencyObject obj)
        {
            return (string)obj.GetValue(DocumentXamlProperty);
        }

        public static void SetDocumentXaml(DependencyObject obj, string value)
        {
            _recursionProtection.Add(Thread.CurrentThread);
            obj.SetValue(DocumentXamlProperty, value);
            _recursionProtection.Remove(Thread.CurrentThread);
        }

        public static readonly DependencyProperty DocumentXamlProperty = DependencyProperty.RegisterAttached(
            "DocumentXaml",
            typeof(string),
            typeof(RichTextBoxHelper),
            new FrameworkPropertyMetadata(
                "",
                FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                (obj, e) =>
                {
                    if (_recursionProtection.Contains(Thread.CurrentThread))
                        return;

                    var richTextBox = (RichTextBox)obj;

                // Parse the XAML to a document (or use XamlReader.Parse())

                try
                    {
                        FlowDocument doc = new FlowDocument();
                        var s = GetDocumentXaml(richTextBox);
                        if (s!=null && s != "")
                        {
                            var stream = new MemoryStream(Encoding.UTF8.GetBytes(s));
                            doc = (FlowDocument)XamlReader.Load(stream);
                        }


                    // Set the document
                    richTextBox.Document = doc;
                    }
                    catch (Exception x)
                    {
                        richTextBox.Document = new FlowDocument();
                    }

                // When the document changes update the source
                richTextBox.TextChanged += (obj2, e2) =>
                    {
                        RichTextBox richTextBox2 = obj2 as RichTextBox;
                        if (richTextBox2 != null)
                        {
                            SetDocumentXaml(richTextBox, XamlWriter.Save(richTextBox2.Document));
                        }
                    };
                }
            )
        );
    }

Richtextbox привязка

                <toolkit:RichTextBox x:Name="_richTextBox"
                                     utilitary:RichTextBoxHelper.DocumentXaml="{Binding Content.StoryBoardContent,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                     FontFamily="Arial"
                                     Background="{x:Null}"
                                     Grid.Row="1"
                                     FontSize="16"
                                     IsDocumentEnabled="True"
                                     ScrollViewer.VerticalScrollBarVisibility="Auto"
                                     Margin="5">

                                     <!--IsReadOnly="{Binding IsReadOnly}"-->
                <toolkit:RichTextBox.TextFormatter>
                    <toolkit:XamlFormatter/>
                </toolkit:RichTextBox.TextFormatter>
                <toolkit:RichTextBox.InputBindings>
                    <KeyBinding Command="{Binding Content.InsertTimecodes}" Modifiers="Ctrl" Key="T" />
                    <KeyBinding Command="{Binding Content.InsertTextBox}" Modifiers="Ctrl" Key="G" />                        
                    </toolkit:RichTextBox.InputBindings>
                </toolkit:RichTextBox>

CustomControls

<UserControl x:Class="Client.Utilitary.SpecialButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Client.Utilitary"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="40"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0" BorderBrush="{x:Null}" >
            <Path Name="Icon"
                  VerticalAlignment="Center"
                  HorizontalAlignment="Center"
                  Data="M11.809003,19.989007C10.414956,19.989007 9.601965,20.484003 9.5139519,20.679987 9.601965,20.781001 10.414956,21.275997 11.809003,21.275997 13.099961,21.275997 13.892017,20.851009 14.072987,20.632991 13.892017,20.412989 13.099961,19.989007 11.809003,19.989007z M11.302998,17.60502C11.347748,17.684269,11.391561,17.764644,11.434406,17.846128L11.50994,17.995136 11.578156,17.992239C11.654417,17.990088 11.731378,17.989002 11.809003,17.989003 14.293019,17.989002 16.096003,19.101004 16.096003,20.632991 16.096003,22.164 14.293019,23.276002 11.809003,23.276002 9.3249866,23.276002 7.5220027,22.164 7.5220023,20.632991 7.5220027,19.436126 8.6224567,18.4956 10.288377,18.141392L10.379956,18.12346z M13.270977,14.336003L15.082981,15.182001C14.83398,15.716,14.60898,16.265,14.41398,16.811999L12.529976,16.141C12.745976,15.535001,12.994977,14.928001,13.270977,14.336003z M8.0269982,14.05702C8.7010067,14.532018,9.3140146,15.061015,9.8480217,15.630011L8.3900028,16.999004C7.9479969,16.528007,7.4389903,16.088009,6.874983,15.691012z M2.9359951,11.661008C2.4199958,11.661008 1.9999967,12.081007 1.9999967,12.597007 1.9999967,13.113006 2.4199958,13.533005 2.9359951,13.533005 3.4519944,13.533005 3.8719938,13.113006 3.8719935,12.597007 3.8719938,12.081007 3.4519944,11.661008 2.9359951,11.661008z M15.216981,10.973007L16.851985,12.125005C16.512984,12.607005,16.191983,13.108004,15.898983,13.613003L14.168979,12.611004C14.49098,12.054005,14.84398,11.504006,15.216981,10.973007z M2.9359951,9.6610117C4.5579927,9.6610117 5.8719906,10.976009 5.8719908,12.597007 5.8719906,12.647694 5.8707074,12.698081 5.8681718,12.748136L5.8627819,12.81906 5.9630038,12.86501 5.8118646,13.191009 5.7795883,13.330922C5.6830721,13.706219,5.5142555,14.052441,5.288857,14.353871L5.2495458,14.4039 5.1219969,14.679016 5.0414798,14.642586 5.0122418,14.673253C4.4809928,15.204503 3.746994,15.533002 2.9359951,15.533002 1.3139977,15.533002 0,14.219004 0,12.597007 0,10.976009 1.3139977,9.6610117 2.9359951,9.6610117z M17.720986,8.006011L19.131988,9.4230089C18.714987,9.8380079,18.311986,10.276008,17.932986,10.725007L16.404983,9.435009C16.819984,8.942009,17.262985,8.4620104,17.720986,8.006011z M20.684991,5.5120144L21.841994,7.143012C21.359993,7.4860115,20.887991,7.8510103,20.438991,8.2280102L19.151989,6.6970119C19.641989,6.2850132,20.157991,5.886013,20.684991,5.5120144z M23.992999,3.5250168L24.893,5.3120146C24.357998,5.5810137,23.831997,5.8700132,23.330997,6.1710129L22.302994,4.4550152C22.845995,4.1290159,23.414997,3.8170166,23.992999,3.5250168z M29.064005,1.9999971C28.548005,1.9999971 28.128006,2.4199963 28.128006,2.9359951 28.128006,3.4519949 28.548005,3.871994 29.064005,3.871994 29.580004,3.871994 30.000002,3.4519949 30.000002,2.9359951 30.000002,2.4199963 29.580004,1.9999971 29.064005,1.9999971z M29.064005,0C30.686001,0 32,1.3149986 32,2.9359951 32,4.5579929 30.686001,5.8719912 29.064005,5.8719912 28.050257,5.8719912 27.156821,5.3587103 26.629302,4.577755L26.597661,4.5283918 26.527991,4.5569983 25.754982,2.7120018 26.154246,2.5486393 26.161826,2.4889898C26.377091,1.0799942,27.594069,0,29.064005,0z"
                  Stretch="Uniform"
                                            Fill="Black"
                                            Width="25"
                                            Height="25" 
                                            Margin="2"/>
        </Border>
        <TextBlock  Name="TextBlock_name" TextWrapping="WrapWithOverflow"  Grid.Column="1" Style="{StaticResource MetroTextBlock}"   Foreground="Black" FontFamily="Arial" FontSize="10" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox Name="TextBlock_detailData" TextWrapping="WrapWithOverflow" Grid.Column="2"  FontFamily="Arial" FontSize="10" Foreground="Black" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{DynamicResource MaterialDesignTextBox}"/>
        <TextBox  Style="{DynamicResource MaterialDesignTextBox}" TextWrapping="Wrap" Grid.Column="3"  Foreground="Black" FontFamily="Arial" FontSize="10" VerticalAlignment="Center" />       
    </Grid>
</UserControl>

Для возможности добавления элементов управления из модели представления добавлен некоторый код в код позади элемента управления

public partial class SpecialButton : UserControl
    {
        public string Name
        {
            get { return TextBlock_name.Text; }
            set { TextBlock_name.Text = value; }
        }
        public string PathData
        {
            get { return Icon.Data.ToString(); }
            set { Icon.Data= Geometry.Parse(value); }
        }
        public string Observation
        {
            get { return TextBlock_detailData.Text; }
            set { TextBlock_detailData.Text = value; }
        }
        public SpecialButton()
        {
            InitializeComponent();
        }
    }

Вот так я могу добавить элементы управления из модели представления

private void SetNodeInStoryboard(Node obj)
        {
            Paragraph p = new Paragraph();
            BlockUIContainer i = new BlockUIContainer(
                new SpecialButton
                {

                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    Background = (SolidColorBrush)new BrushConverter().ConvertFromString(FieldTypesList.FirstOrDefault(x => x.Name == "VIDEOSRC").Color),
                    PathData = FieldTypesList.FirstOrDefault(x => x.Name == "VIDEOSRC").Icon,
                    Name =obj.Name,
                    Observation = obj.SelectedTimeCode.TimeCode,
                    Foreground = System.Windows.Media.Brushes.Black
                });

            i.Tag = obj.NodeGuid;
            //p.Add(i);
            MessengerInstance.Send<Block>(i, MessageTypes.InsertBlock);
            MessengerInstance.Send<Node>(obj, MessageTypes.NewVideoSelected);

        }

Richtextbox выглядит примерно так:

enter image description here

Ошибка при загрузке потокового документа из БД

enter image description here

Теперь у кого-нибудь есть обходной путь для этого или, возможно, другого подхода

Заранее спасибо,

...