7

FlowDocumentがXPSドキュメントとして保存されたときに表示するために、FlowDocumentに含まれる画像を取得するのに問題があります。

これが私がすることです:

  1. WPFのImageコントロールを使用して画像を作成します。BeginInit/EndInitの呼び出しで囲まれた画像ソースを設定しました。
  2. 画像をFlowDocumentに追加し、BlockUIContainerでラップします。
  3. このコードの変更バージョンを使用して、FlowDocumentオブジェクトをXPSファイルに保存します。

次に、保存したファイルをXPSビューアーで表示すると、画像が表示されません。問題は、画像がWPFによって実際に画面に表示されるまで読み込まれないため、XPSファイルに保存されないことです。したがって、回避策があります。最初にFlowDocumentPageViewerを使用して画面にドキュメントを表示し、その後XPSファイルを保存すると、画像が読み込まれ、XPSファイルに表示されます。これは、FlowDocumentPageViewerが非表示になっている場合でも機能します。しかし、それは私に別の挑戦を与えます。これが私がやりたいことです(擬似コードで):

void SaveDocument()
{
    AddFlowDocumentToFlowDocumentPageViewer();
    SaveFlowDocumentToXpsFile();
}

もちろん、これは機能しません。ドキュメントがXPSファイルに保存される前に、FlowDocumentPageViewerがその内容を表示する機会がないためです。Dispatcher.BeginInvokeの呼び出しでSaveFlowDocumentToXpsFileをラップしようとしましたが、役に立ちませんでした。

私の質問は次のとおりです。

  1. ドキュメントを実際に画面に表示せずに、XPSファイルを保存する前に画像を強制的にロードすることはできますか?(運が悪か​​ったので、 BitmapImage.CreateOptionsをいじってみました)。
  2. 質問1の解決策がない場合、FlowDocumentPageViewerがコンテンツの読み込みを完了したことを通知して、XPSファイルを作成するためにいつ保存されるかを知る方法はありますか?
4

4 に答える 4

3

最終的な解決策は、ドキュメントをビューアに配置して画面に簡単に表示するという、あなたがたどり着いたものと同じでした。以下は、私がこれを行うために作成したヘルパーメソッドです。

private static string ForceRenderFlowDocumentXaml = 
@"<Window xmlns=""http://schemas.microsoft.com/netfx/2007/xaml/presentation""
          xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
       <FlowDocumentScrollViewer Name=""viewer""/>
  </Window>";

public static void ForceRenderFlowDocument(FlowDocument document)
{
    using (var reader = new XmlTextReader(new StringReader(ForceRenderFlowDocumentXaml)))
    {
        Window window = XamlReader.Load(reader) as Window;
        FlowDocumentScrollViewer viewer = LogicalTreeHelper.FindLogicalNode(window, "viewer") as FlowDocumentScrollViewer;
        viewer.Document = document;
        // Show the window way off-screen
        window.WindowStartupLocation = WindowStartupLocation.Manual;
        window.Top = Int32.MaxValue;
        window.Left = Int32.MaxValue;
        window.ShowInTaskbar = false;
        window.Show();
        // Ensure that dispatcher has done the layout and render passes
        Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Loaded, new Action(() => {}));
        viewer.Document = null;
        window.Close();
    }
}

編集:window.ShowInTaskbar = falseタスクバーにウィンドウが表示されるのをすばやく確認できるかのように、メソッドに追加しました。

ウィンドウが画面の外に配置されているため、ユーザーがウィンドウを「見る」ことは決してありません。これはInt32.MaxValue、初期のマルチメディアオーサリング(Macromedia / Adob​​e Directorなど)で一般的だったトリックです。

この質問を検索して見つけた人にとって、ドキュメントを強制的にレンダリングする方法は他にありません。

HTH、

于 2012-02-27T11:37:11.250 に答える
1

いくつかのこと...あなたは画像が書かれる前にサイズが決められていることを確認しますか?通常、コントロールでMeasureを呼び出して、それに応じてサイズを変更できるようにする必要があります(無限大により、コントロールは幅と高さに拡張されます)

image.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

また、コントロールですべてが更新されるように、UIスレッドをバンプする必要がある場合もあります

Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>{}));
于 2011-01-18T19:18:33.540 に答える
0

画像をXPSに保存するために、ドキュメントを表示する必要はありません。XpsSerializationManagerでcommitを呼び出していますか?

FlowDocument fd = new FlowDocument();

        fd.Blocks.Add(new Paragraph(new Run("This is a test")));

        string image = @"STRING_PATH";

        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        bi.UriSource = new Uri(image, UriKind.RelativeOrAbsolute);
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.EndInit();
        MemoryStream ms = new MemoryStream();
        Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
        Uri pkgUri = bi.UriSource;

        PackageStore.AddPackage(pkgUri, pkg);


        Image img = new Image();
        img.Source = bi;

        BlockUIContainer blkContainer = new BlockUIContainer(img);

        fd.Blocks.Add(blkContainer);


        DocumentPaginator paginator = ((IDocumentPaginatorSource)fd).DocumentPaginator;

      using (XpsDocument xps = new XpsDocument(@"STRING PATH WHERE TO SAVE FILE", FileAccess.ReadWrite, CompressionOption.Maximum))
        {
            using (XpsSerializationManager serializer = new XpsSerializationManager(new XpsPackagingPolicy(xps), false))
            {
                serializer.SaveAsXaml(paginator);
                serializer.Commit();
            }
        }
于 2012-03-12T13:38:44.627 に答える
0

フロードキュメントをビューアにスローして、測定/配置を行うことで、これに対処することができました。

FlowDocumentScrollViewer flowDocumentScrollViewer = new FlowDocumentScrollViewer();
flowDocumentScrollViewer.Document = flowDocument;
flowDocumentScrollViewer.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
flowDocumentScrollViewer.Arrange(new Rect(new Point(0, 0), new Point(Double.MaxValue, Double.MaxValue)));
于 2020-01-16T01:06:49.813 に答える