在多个 RichTextBox 之间共享 FlowDocument

发布于 2024-07-16 11:38:41 字数 641 浏览 5 评论 0原文

WPF FlowDocument 只能属于单个 RichTextBox。 但是,我们希望使用可以在 UI 中的不同点(空间和时间)进行操作的单个文档。 永远不会出现两个 RichTextBox 同时显示单个文档的情况(而且也不可能,因为 WPF 会抱怨)。

使用 MemoryStreamXamlReader/Writer 在这里不起作用,因为我们希望保留单个文档并在使用它的任何地方反映更改,所以每次都复制它是不行的。

有没有其他可行的方法来实现这一目标? 您可以使用什么作为基础模型来创建 FlowDocument 等?

澄清:当实例化另一个 RichTextBox 时,使用该文档的 RichTextBox 将不再可见,也不再位于逻辑/可视树中的任何位置。 虽然我可能无法强制他们已经被 GC 吃掉了。 从窗口中删除 RichTextBox 后立即重新使用文档时,这似乎会导致问题; 仍然会抛出一个异常,即该文档已在另一个控件中使用。

基本上是有一组依次显示的“向导页面”,并且我们可能会在两个连续的“页面”上重复使用文档,但每次都会实例化一个新的 RTBox。 也许有问题或者有更好的方法?

A WPF FlowDocument can only belong to a single RichTextBox. However, we'd like to use a single document which can be manipulated at different points (in space and time) in the UI. It will never happen that there are two RichTextBoxes simultaneously displaying a single document (and can't, because WPF will complain).

Using a MemoryStream and XamlReader/Writer won't work here as we would like to retain a single document and reflect changes wherever it is used, so copying it every time is out.

Is there any other viable way to achieve that? Something you could use as underlying model from which to create FlowDocuments or so?

Clarification: The RichTextBoxes that use the Document are no longer visible or anywhere in the logical/visual tree when another one will be instantiated. Though I probably can't enforce that they have already been eaten by the GC. Seemingly this causes a problem when re-using the Document immediately after removing the RichTextBox from the window; that still throws an exception that the Document is already used in another control.

Basically be have a set of "wizard pages" that are displayed one after another and it can happen that we re-use the Document on two successive "pages" but instantiate a new RTBox each time. Maybe there's a problem or a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

于我来说 2024-07-23 11:38:41

FlowDocument 无法直接由多个 RichTextBox 控件共享。

因此,您需要先“分离”该文档...

所以

RTB2.Document = RTB1.Document;

不起作用,并且会导致异常。.

FlowDocument doc = RTB1.Document;
RTB1.Document = new FlowDocument(); //Document cannot be null, so therefor the new FlowDocument instance
RTB2.Document = doc;

将像魅力一样工作...

我的代码示例:

Xaml:

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>


        <RichTextBox x:Name="RTB1" />

        <RichTextBox x:Name="RTB2" Grid.Column="1" />

        <Button x:Name="button" Grid.Row="1" Grid.ColumnSpan="2" Content="click" Click="button_Click"  />

    </Grid>

</Window>

背后的代码..

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        FlowDocument doc = RTB1.Document;
        RTB1.Document = new FlowDocument();
        RTB2.Document = doc;
    }
}

它不是书中最漂亮的,但它有效...

希望这有帮助..

The FlowDocument cannot be shared by several RichTextBox controls directly..

So you need to 'detach' that document first...

So

RTB2.Document = RTB1.Document;

wont work and will result in your exception..

FlowDocument doc = RTB1.Document;
RTB1.Document = new FlowDocument(); //Document cannot be null, so therefor the new FlowDocument instance
RTB2.Document = doc;

will work like a charm...

My code sample:

Xaml:

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>


        <RichTextBox x:Name="RTB1" />

        <RichTextBox x:Name="RTB2" Grid.Column="1" />

        <Button x:Name="button" Grid.Row="1" Grid.ColumnSpan="2" Content="click" Click="button_Click"  />

    </Grid>

</Window>

Code behind..

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        FlowDocument doc = RTB1.Document;
        RTB1.Document = new FlowDocument();
        RTB2.Document = doc;
    }
}

Its not the prettiest in the book, but it works...

Hope this helps..

玩心态 2024-07-23 11:38:41

根据您的向导的构建方式,我实际上建议您只需将 RichTextBox 从一个页面移动到另一个页面即可。 WPF 控件可以随意“取消父级”和“重新设置父级”,因此只需使 RichTextBox 实例在整个向导共享的上下文中可用,并确保在从一个页面移动到另一个页面时取消/重新设置父级。 这还有一个好处是可以保存向导中跨页面的编辑器状态的任何样式或更改(这可能是可取的)。

如果无法跨页面共享 RichTextBox 实例,我认为有一种方法可以将文档与原始 RichTextBox 解除关联。 看来,为了取消该文档与 RichTextBox1 的关联,您必须为 RichTextBox1 提供一个新文档。 您不能将 RichTextBox1.Document 设置为 null,但可以将 RichTextBox1.Document 设置为 new FlowDocument(),我相信这会起作用。 我现在无法对此进行测试,但我看到此 MSDN 论坛主题的最后一篇文章中推荐了它:

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/797bfc96-cf24-4071-bff8- ce8c4a7b897b

Depending on how your wizard is constructed I actually would recommend you simply move the RichTextBox from page to page. WPF controls can be ‘unparented’ and ‘reparented’ at will, so just make the RichTextBox instance available in the context shared throughout your wizard and make sure you unparent / reparent as you move from page to page. This also has the benefit of saving any styles or changes to the editors state across pages in the wizard (which is probably desirable).

If it isn’t possible to share the RichTextBox instance across pages, I think there is a way to disassociate the document from the original RichTextBox. It appears that in order to disassociate the document from RichTextBox1, you have to provide RichTextBox1 with a new document. You can’t set RichTextBox1.Document to null, but you CAN set RichTextBox1.Document to new FlowDocument() and I believe that will work. I’m unable to test this right now, but I saw it was recommended in the last post of this MSDN forum thread:

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/797bfc96-cf24-4071-bff8-ce8c4a7b897b

鸠魁 2024-07-23 11:38:41

如果在任何给定时间界面中只有一个编辑器可见,我认为可以在活动编辑器的 LostFocus 事件中同步所有编辑器的内容。

如果一个编辑器中的更改需要立即反映在应用程序的另一个当前可见部分中,您可以通过使用矩形来伪造它,例如,其中填充是引用活动编辑器的 VisualBrush,并且矩形的宽度和高度绑定到编辑器的实际宽度和高度。 棘手的部分是以相对无缝的方式处理活动编辑器切换。

编辑:我想我不明白为什么在向导中的页面之间移动时不能执行 XamlWriter.Save / XamlReader.Parse 序列,但是...使用相同的 RichTextBox 实例怎么样?当该页面变得可见/活动时,将其重新设置为每个页面中的容器的父级?

If only one editor is visible in the interface at any given time, I should think it would be possible to synchronize the contents of all editors in the LostFocus event of the active editor.

If changes in one editor need to be reflected immediately in another currently visible part of the app, you could fake it by using a Rectangle, say, where the Fill was a VisualBrush referencing the active editor and the Rectangle's width and height were bound to the editor's actual width and height. The tricky part would be handling the active editor switch in a relatively seamless fashion.

EDIT: I guess I don't understand why you cannot do a XamlWriter.Save / XamlReader.Parse sequence when moving between pages in the wizard, but...what about using the same RichTextBox instance all the time and re-parent it to a container in each page when that page becomes visible/active?

美煞众生 2024-07-23 11:38:41

流程文档无法共享,因此您必须分离。

string flowDocument = XamlWriter.Save(RTF1.Document);
RichTextBox RTF2= new RichTextBox();
RTF2.Document = XamlReader.Load(new MemoryStream(Encoding.Default.GetBytes(flowDocument))) as FlowDocument; 

Flow document can not be share so you have to detach.

string flowDocument = XamlWriter.Save(RTF1.Document);
RichTextBox RTF2= new RichTextBox();
RTF2.Document = XamlReader.Load(new MemoryStream(Encoding.Default.GetBytes(flowDocument))) as FlowDocument; 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文