I have a test app where i'm trying to insert an editable paragraph so user can write info there (maybe it can be realized just with Run, i took paragraph just for example, if you know how to add Run into Run, that will be great). I DON'T WANT to use richtextbox for it for two main reasons:
User can't edit any other parts of document
Flowdocument has pagination For what i've done now, i have this: textbox and flowdocument with one paragraph (aaaaa bbb cccc) created by xaml and one created by code
My editable paragraph going to the end of document. What i want is to put it instead of "bbb" for examle. So it must somehow find "bbb" from all document, replace it, and put in that place my paragraph
I've tried to:
- Run through all blocks, find text that i need and remove it from paragraph, but no use because i can't replace string with paragraph or with run
- Find index of text i want but i still can't do nothing with it because i need a TextPointer
- Convert int to TextPointer but documentation said i'm going to a wrong and unsave direction
- Find cursor controller for FlowDocument and set it to index i need but it still needs a TextPointer So i really need help because i can't see no other options
Here is my xaml
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<FlowDocumentReader Grid.Row="1">
<FlowDocument x:Name="DocumentReader"/>
</FlowDocumentReader>
</Grid>
And here is my xaml.cs without any bad code with my attempts to set paragrahp inside a paragraph - just textbox and editable paragraph
Dictionary<string, Paragraph> paragraphs = new Dictionary<string, Paragraph>();
private string text = $"{{\\rtf1\\ansi\\ansicpg1252\\uc1\\htmautsp\\deff2{{\\fonttbl{{\\f0\\fcharset0 Times New Roman;}}{{\\f2\\fcharset0 Palatino Linotype;}}}}{{\\colortbl\\red0\\green0\\blue0;\\red255\\green255\\blue255;}}\\loch\\hich\\dbch\\pard\\plain\\ltrpar\\itap0{{\\lang1033\\fs21\\f2\\cf0 \\cf0\\ql{{\\f2 {{\\ltrch aaaaa bbb ccc}}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}}\r\n}}\r\n}}";
public MainWindow()
{
InitializeComponent();
//this is how data loads in flowdocument in my actual programm
TextRange textRange = new TextRange(DocumentReader.ContentStart, DocumentReader.ContentEnd);
using (MemoryStream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(text)))
{
textRange.Load(stream, DataFormats.Rtf);
}
//this is what i was testing
var parag = new Paragraph { Name = "paragName" };
parag.Inlines.Add(new Run("as"));
paragraphs.Add("paragName", parag);
DocumentReader.Blocks.Add(parag);
var txt = new TextBox{Tag = "paragName" };
txt.TextChanged += (sender, args) =>
{
paragraphs.First(x => (string)x.Key == txt.Tag).Value.Inlines.Clear();
paragraphs.First(x => (string)x.Key == txt.Tag).Value.Inlines.Add(new Run((sender as TextBox).Text));
};
grid.Children.Add(txt);
}
It is super raw, i was just testing it, but i can't resolve how to do it, please help
A quite simple solution would be to use a
TextBlockand then inline aTextBoxat the position you like to edit.The following example lets
EditableTextBlockextendTextBlockto extend theTextBlockbehavior.Setting a
EditableTextBlock.EditableTextRangeproperty defines the position and range in the text which should be made editable. The complete displayed text can be obtained by accessing the inheritedEditableTextBlock.Textproperty as usual.Setting the
EditableTextBlock.EditableTextRangeproperty will trigger aTextBoxto appear at the specified position. The edited value is then committed by pressing the Enter key or by clicking theButtonnext to theTextBox.The
TextBoxwill then disappear and the edited text will become read-only again.To simplify the content handling, the
EditableTextBlockmaintains a single Run to display the content.The implementation is very simple and should serve you as a useful starting point.
TextRange.cs
EditableTextBlock.cs
App.xaml
Usage example
MainWindow.xaml
MainWindow.xaml.cs