Why can't I paste text copied from a WPF FlowDocumentScrollViewer or Reader?
Asked Answered
B

1

6

In a previous question I was trying to find out how to bind an ObservableCollection to a control so I could both see all the strings and select all the strings and copy them from the content control. The answers to that question eventually got me the look (and seemingly the behavior)I wanted by using the following XAML. (I tried both a FlowDocumentReader and FlowDocumentScrollViewer - they behave the same.)

<Grid>
<FlowDocumentScrollViewer>
    <FlowDocument >
        <Paragraph>
            <ItemsControl ItemsSource="{Binding ErrorMessages, Mode=OneWay}" />
            <Run Text="{Binding /, Mode=OneWay}" />
        </Paragraph>
    </FlowDocument>
</FlowDocumentScrollViewer>
</Grid>

ErrorMessages is my ViewModel property that returns an ObservableCollection<string>. It binds properly to the ItemsSource and the <Run> element binds to each string in the collection. Looks good, lasts a long time. This was so close I marked my last question as answered but I still have one problem.

I right click and a menu shows up with the Select All and Copy options. Using Select All, does indeed highlight all the text, selecting Copy issues no errors, but when I go to NotePad (or Word, or TextPad etc. or a RTB on the form) and try to paste the text, nothing ever shows up. As a newcomer to WPF I suspect I'm doing something wrong but I don't know what it is. There's no such thing as "lookless" text is there?

[Edit -June 22 2011] For other reasons I've changed the code to use a TextBlock via an ItemTemplate inside the ItemsControl as shown below, but I still can't copy and paste.

<DataTemplate x:Key="StringCollection">
   <TextBlock TextWrapping="Wrap" Text="{Binding}" TextAlignment="Left"/>
</DataTemplate>
<!--... now down in the ItemsControl-->
<ItemsControl ItemsSource="{Binding ReceivedData, Mode=OneWay}"
      ItemTemplate="{StaticResource StringCollection}" />
Banksia answered 14/6, 2011 at 21:23 Comment(2)
You can inspect clipboard (there is a Clipboard class in .Net) right after the Copy and check if it contains text and what other data types were copied.Knap
OK - When I capture the GetFormats() it shows Xaml, ApplicationTrust, Text, UnicodeText, System.String, Rich Text Format. When I check GetDataPresent(DataFormats.Text) and it passes I displayed the "Got Text:" followed by the actual clipboard text in a variable clip_text followed by the clip_text.Length() Got Text: 4 where there was nothing between Got Text: and the 4 was on the next line. What's that mean? 4 non-displayable characters one of which is a new line? The actual data selected and copied were the three strings Fake Error 1 Fake Error 2 Manually added in InstrumentViewModel.Banksia
K
3

<Run> element binds to each string in the collection.

It only should bind to the current element if anything.

Anyway, your document does in fact not contain any text at all if all you have is the ItemsControl. Why? Because any UIElements inside the document are automatically wrapped in a BlockUIContainer or InlineUIContainer and are no longer considered to be text.

In general the content is copied as XAML, RTF, UnicodeText & Text (i could observe those, but there might be other formats), you can try to place some Runs in your document, their text should be copied properly and Clipboard.GetText() should return their contents.

Kyoko answered 26/6, 2011 at 13:35 Comment(5)
I don't understand, when you say "your document does in fact not contain any text at all". It looks like it has text. I can see it, and I can select it. In case you didn't notice in the 2nd iteration I used a TextBlock but the behavior was the same. Regardless I'm not sure what you're suggesting I do. I originally had a <Run> and that didn't work. How is placing more Runs going to help? I have a potentially changing number of messages and I want to display them (working as shown) but I also want to copy them to the clipboard. What should I change?Banksia
Somehow your message got lost in my inbox. Anyway, TextBlocks are not text either, they are also UIElements which get wrapped in containers and are not treated like text. I suggest you take an entirely different approach to this, like concatenating the strings as i suggested in my answer to your earlier question, then you can use a single Run to display that text.Kyoko
Further, even if the items of the ItemsControl were flow content (which is not possible), you still would have the ItemsControl itself which would be wrapped in a container making those efforts pointless.Kyoko
OK - Thanks. I believe I understand now, let me rephrase and see if you concur. I should replace what is inside my <Paragraph> element with a single <Run> element. Then I should write a converter to convert my ObservableCollection<string> into a single text element (hopefully with line feeds - to preserve the current view) and put the results inside that <Run> element. Then I will get the same look BUT add the ability to copy what is there. Correct?Banksia
@Tod: That sounds about right, yes. There might be other ways but this seems to be one of the easier methods. You could also hook into the copy command and copy the messages to the clipboard manually.Kyoko

© 2022 - 2024 — McMap. All rights reserved.