質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

2777閲覧

【C#】【WPF】リッチテキストボックスに貼り付けた画像をバイナリーに保存して次回起動した際に表示したい

OXamarin

総合スコア59

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

1クリップ

投稿2019/08/25 06:04

##前提
環境:VS2019
言語:C# WPF
フレームワーク:MVVM

##最終的に達成したい事
以下のような、クリップボードを監視して履歴を保持するようなアプリケーションを作成しています。
イメージ説明]

アプリケーションを閉じて再度起動した際に、リッチテキストボックスに貼り付けられていた画像をリッチテキストボックスに貼れるようにFlowDocument型に戻してやりたい。
テキストボックスに関してはうまくFlowDocument型に戻せています。

##悩んでいる事
リッチテキストボックスに貼った画像を、次回起動時にFlowDocument型にして復元することができない。

##現状
リッチテキストボックスのDocumentプロパティ(FlowDocument型)をバイナリーへそのまま変換する事ができないので、以下の手順で変換・復元を行う。

  1. XamlWriteを使用してXamlへ一旦文字列変換する
  2. アプリケーション起動時に、そのXaml文字列をFlowDocumentへ変換する
  3. リッチテキストボックスのDocumentプロパティへバインドさせてやることで内容を復元する

具体例として、
「Teratail」という文字列を持ったFlowDocumentをXaml文字列へ変換した場合、以下のようなXamlになります。

Xaml

1<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> 2 <Paragraph>Teratail</Paragraph> 3</FlowDocument>

これであれば、難なくFlowDocument型へ戻すことができます。
念の為ですが、以下の様に表示されます。
イメージ説明

画像を持ったFlowDocumentを変換した場合、以下のようなXamlになります。

Xaml

1<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:swi="clr-namespace:System.Windows.Interop;assembly=PresentationCore"> 2 <Paragraph> 3 <Image> 4 <Image.Source> 5 <swi:InteropBitmap /> 6 </Image.Source> 7 </Image> 8 </Paragraph> 9</FlowDocument>

アプリケーション起動中であれば、FlowDocumentを生成するので以下の様に表示できます。
イメージ説明]

このXamlを復元しようとすると以下の様な例外が発生します
イメージ説明

一致するコンストラクターが型 'System.Windows.Interop.InteropBitmap' に見つかりません。この型は、引数または FactoryMethod ディレクティブを使用して構築できます。

どのようにすれば、リッチテキストボックスの画像を復元できるのでしょうか。

##コード
FlowDocument ⇔ Xaml の変換には以下のコードを使用しています。
どこかのStackOverFlowの記事のロジックを持ってきていましたが、どこからかは失念してしまいました。

C#

1/// <summary> 2/// FlowDocumentをXaml文字列へ変換 3/// </summary> 4/// <param name="flowDocument"></param> 5/// <returns></returns> 6public static string ToXamlString(this IDocumentPaginatorSource flowDocument) 7{ 8 return XamlWriter.Save(flowDocument); 9} 10/// <summary> 11/// Xaml文字列をFlowDocumentへ変換 12/// </summary> 13/// <param name="xamlString"></param> 14/// <returns></returns> 15public static FlowDocument ToFlowDocument(this string xamlString) 16{ 17 if (IsFlowDocument(xamlString)) 18 { 19 var stringReader = new StringReader(xamlString); 20 var xmlReader = XmlReader.Create(stringReader); 21 22 return XamlReader.Load(xmlReader) as FlowDocument; 23 } 24 else 25 { 26 var myParagraph = new Paragraph(); 27 myParagraph.Inlines.Add(new Run(xamlString)); 28 var myFlowDocument = new FlowDocument(); 29 myFlowDocument.Blocks.Add(myParagraph); 30 31 return myFlowDocument; 32 } 33} 34/// <summary> 35/// 36/// </summary> 37/// <param name="xamlString"></param> 38/// <returns></returns> 39private static bool IsFlowDocument(this string xamlString) 40{ 41 if (string.IsNullOrEmpty(xamlString)) 42 { 43 throw new ArgumentNullException(); 44 } 45 46 if (xamlString.StartsWith("<") && xamlString.EndsWith(">")) 47 { 48 var xml = new XmlDocument(); 49 try 50 { 51 xml.LoadXml(string.Format("<Root>{0}</Root>", xamlString)); 52 return true; 53 } 54 catch (XmlException) 55 { 56 return false; 57 } 58 } 59 return false; 60}

##他に参考にしたもの
以下のソースを使用して変換を試みましたが、うまく扱えませんでした。
StackOverFlow - C#WPFは、richtextboxに貼り付けられたBitmapImageをバイナリに変換します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決しました。

結論からいくと、以下のメソッドでImageを持ったFlowDocumentをシリアライズ・デシリアライズできます。

C#

1/// <summary> 2/// バイナリ化したFlowDocumentをデシリアライズする 3/// </summary> 4/// <param name="byteArray"></param> 5/// <returns></returns> 6public static FlowDocument ToFlowDocument(this byte[] byteArray) 7{ 8 using (var ms = new MemoryStream(byteArray)) 9 { 10 var flowDocument = new FlowDocument(); 11 var textRange = new TextRange(flowDocument.ContentStart,flowDocument.ContentEnd); 12 textRange.Load(ms,DataFormats.XamlPackage); 13 return flowDocument; 14 } 15} 16/// <summary> 17/// FlowDocumentをバイナリ化する 18/// </summary> 19/// <param name="document"></param> 20/// <returns></returns> 21public static byte[] ToBinary(this FlowDocument document) 22{ 23 using (var ms = new MemoryStream()) 24 { 25 var range = new TextRange(document.ContentStart, document.ContentEnd); 26 range.Save(ms, DataFormats.XamlPackage); 27 ms.Seek(0, SeekOrigin.Begin); 28 return ms.ToArray(); 29 } 30}

以下の質問への回答にまんま書いてありました。
RichTextboxのコンテンツの保存と読み込み

自分なりに調べたことを残しておきます。

質問内容にも書きましたが、、
画像を持ったFlowDocumentを変換した場合、以下のようなXamlになります。

Xaml

1<FlowDocument 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:swi="clr-namespace:System.Windows.Interop;assembly=PresentationCore"> 4 <Paragraph> 5 <Image> 6 <Image.Source> 7 <swi:InteropBitmap /> 8 </Image.Source> 9 </Image> 10 </Paragraph> 11</FlowDocument>

これで何故、参照しているはずのモジュールが参照されないのかは分かりませんが、Imageを含んだコントロールをXamlWriterが正しく処理出来ていない事が原因のようだったので、早々にXamlWriterでの解決は諦めました。

FlowDocumentのシリアライズ方法について検索すると、幾つかTextRangeを使用した方法がヒットします。どうやらTextRange.SaveにはInlineUIContainer要素をシリアライズする機能があるらしく、その機能を使っているようでした。
FlowDocument
Paragrah
InlineUIContainer
Image
という階層になっているので、確かにTextRange.Saveを使えばFlowDocumentをうまいことシリアライズできそうだということで試行錯誤してたどりつけました。勿論、文字列にも対応できています。

DataFormats.XamlPackage が何なのかは正直わかってないですがMSのページでもデータフォーマットはXamlPackageとしているのでとりあえずXaml形式にしておけばよさげでした。
方法: RichTextBox コンテンツの保存、読み込み、および印刷

投稿2019/08/26 15:20

OXamarin

総合スコア59

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問