apply text formatting from string to text for FlowDocument in richtextbox - xaml

I know that when adding text/content/DataContext in XAML you refer to resource dictionary or inline mark up for styling around text or in template.
Q:
However I'm having trouble trying to find a way to do the following:
Data is coming from a View Model/Model that is pulled from a database.
(string value)
I am a <Bold>smart</Bold> man.
to show in a flow document like this:
I am a smart man.
Q end
Either by binding to a converter, behavior, or would saving the paragraph/document that I put in the flow document to a .rtf file in memory stream be a better option?
I've tried to utilize the option for behavior listed > here < but that is for text block and unable to redirect for type text instead of text block.
Trying to make it streamlined.
Tried to use data binding and apply the converter but even though I have the resource for the behavior / converter, it work due to the type conversion.

One clever solution is presented by Rockford Lhotka in post Set rich text into RichTextBlock control. His idea is to create a custom control which then creates the RichTextBlock using XamlReader.Load.
This allows you to use code like the following:
<local:RichTextDisplay Xaml="{Binding Hello}" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
Where Hello is:
public string Hello { get; set; } = "I am a <Bold>smart</Bold> man.";
With a result:
If you use UWP/Win 8.1 XAML, you can use the original code from the blog post with the following small change (Paragraphs added):
<UserControl
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006"">
<Grid>
<RichTextBlock><Paragraph>");
xaml.Append(ctl.Xaml);
xaml.Append(#"
</Paragraph></RichTextBlock>
</Grid>
</UserControl>
");

To answer my own question:
My case was creating a Document style display for user to update and save as a PDF, but I didn't want to rely on Office being on our application Server.
So I resolved this in my case by using a full "doc.RTF" document and importing that as a memory stream/string and apply my needed updates for values to that.
i.e. VB.net snippet example
Using uStream = Assembly.GetExecutingAssembly.GetManifestResourceStream("Resourcefilepath.rtf")
Using mStream As system.IO.MemoeryStream = New MemoryStream()
uStream.CopyTo(mStream)
rtfstring = Encoding.UTF8.GetSTring(mStream.toArray())
'--Do the updates to the needed string as needed:
rtfstring.Replace("Value","UpdatedValue")
'--Load Property Memory String this method is returnind
RTFDataProperty = New MemoryStream(Encoding.UTF8.GetBytes(rtfstring))
End Using
End Using
Then I loaded my XAML Rich Text Box with that memory stream as DataFormats.Rtf.
RichTextBox1.SelectAll()
RichTextBox1.Selection.Load(ClassName.RTFDataProperty, DataFormats.Rtf)
This gave me a template for formatting and layout of that document. (More of a case scenario and not a normal practice)
I also wanted to apply a starting selection so here is what I did there:
'--Get my RichTextBox Text
rtbtext As String = New TextRange(RichTextBox1.Document.contentStart, RichTextbox1.Document.ContentEnd).Text
Dim strStartSelection As String = "Comments..."
Dim startTP As TextPointer
Dim endTP As TextPointer
'--Loop through the paragraphs of the richtextbox for my needed selection starting point:
For Each para As Paragraph In RichTextBox1.Document.Blocks
Dim paraText As String = New TextRange(para.ContentStart, para.ContentEnd).Text
If paraText = "" Then
Dim pos As TextPointer = para.ContentStart
startTP = pos
endTP = startTP.GetPositionAtOffset("".Length + 3) '--my string had ... on the end so had to add for avoiding the escape of that on length
RichTextBox1.Selection.Select(startTP, endTP)
RichTextBox1.Focus()
Exit For
End If
Next
This is the simple VB.net code layout, but you can simplify and adjust from there if you find it useful.
Thanks

Related

Append to meeting invite body with or without Redemption

We are developing an Outlook VSTO add-in.
Right now I am trying to append some information to a meeting invite the user is in the process of composing. I want the content to appear in the body like what clicking the Teams-meeting button would do, where formatted text and links are appended to the end of the body.
Since the content is HTML and the Outlook Object Model does not expose an HTMLBody property for AppointmentItems, I try to set it via Redemption:
// Dispose logic left out for clarity but everything except outlookApplication and outlookAppointment is disposed after use
Application outlookApplication = ...;
AppointmentItem outlookAppointment = ...; // taken from the open inspector
NameSpace outlookSession = outlookApplication.Session;
RDOSession redemptionSession = RedemptionLoader.new_RDOSession();
redemptionSession.MAPIOBJECT = outlookSession.MAPIOBJECT;
var rdoAppointment = (RDOAppointmentItem)redemptionSession.GetRDOObjectFromOutlookObject(outlookAppointment);
string newBody = transform(rdoAppointment.HTMLBody); // appends content right before HTML </body> tag
rdoAppointment.BodyFormat = (int)OlBodyFormat.olFormatHTML;
rdoAppointment.HTMLBody = newBody;
Problem
The Outlook inspector window is not updating with the appended content. If I try to run the code again, I can see the appended content in the debugger, but not in Outlook.
Things I have tried:
Saving the RDOAppointmentItem
Also adding the content to Body property
Using SafeAppointmentItem instead of RDOAppointmentItem; didn't work because HTMLBody is a read-only property there
Setting PR_HTML via RDOAppointment.Fields
Paste the HTML via WordEditor (see below)
Attempt to use WordEditor
Per suggestion I also attempted to insert the HTML via WordEditor:
// Dispose logic left out for clarity but everything except inspector is disposed after use
string htmlSnippet = ...;
Clipboard.SetText(htmlSnippet, TextDataFormat.Html);
Inspector inspector = ...;
Document wordDoc = inspector.WordEditor;
Range range = wordDoc.Content;
range.Collapse(WdCollapseDirection.wdCollapseEnd);
object placement = WdOLEPlacement.wdInLine;
object dataType = WdPasteDataType.wdPasteHTML;
range.PasteSpecial(Placement: ref placement, DataType: ref dataType);
... but I simply receive the error System.Runtime.InteropServices.COMException (0x800A1066): Kommandoen lykkedes ikke. (= "Command failed").
Instead of PasteSpecial I also tried using PasteAndFormat:
range.PasteAndFormat(WdRecoveryType.wdFormatOriginalFormatting);
... but that also gave System.Runtime.InteropServices.COMException (0x800A1066): Kommandoen lykkedes ikke..
What am I doing wrong here?
EDIT: If I use Clipboard.SetText(htmlSnippet, TextDataFormat.Text); and then use plain range.Paste();, the HTML is inserted at the end of the document as intended (but with the HTML elements inserted literally, so not useful). So the general approach seems to be okay, I just can't seem to get Outlook / Word to translate the HTML.
Version info
Outlook 365 MSO 32-bit
Redemption 5.26
Since the appointment is being displayed, work with the Word Object Model - Inspector.WordEditor returns the Document Word object.
Per Dmitrys suggestion, here is a working solution that:
Shows the inserted content in the inspector window.
Handles HTML content correctly with regards to both links and formatting (as long as you stay within the limited capabilities of Words HTML engine).
using System;
using System.IO;
using System.Text;
using Outlook = Microsoft.Office.Interop.Outlook;
using Word = Microsoft.Office.Interop.Word;
namespace VSTO.AppendHtmlExample
{
public class MyExample
{
public void AppendAsHTMLViaFile(string content)
{
// TODO: Remember to release COM objects range and wordDoc and delete output file in a finally clause
Outlook.Inspector inspector = ...;
string outputFolderPath = ...;
string outputFilePath = Path.Combine(outputFolderPath, "append.html");
Word.Document wordDoc = inspector.WordEditor;
File.WriteAllText(outputFilePath, $"<html><head><meta charset='utf-8'/></head><body>{content}</body></html>", Encoding.UTF8);
Word.Range range = wordDoc.Content;
range.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
object confirmConversions = false;
object link = false;
object attachment = false;
range.InsertFile(fileName,
ConfirmConversions: ref confirmConversions,
Link: ref link,
Attachment: ref attachment);
}
}
}

How can i show the image name when i taking a picture?

Im trying to show the name of the image i take with my Camera but i dont know how.
Do i need a another function to show the image name?
My Code for taking picture:
Public Function takePicture() As String
Dim url = THETA_URL & "commands/execute"
Dim payload = New Dictionary(Of Object, Object) From {
{"name", "camera.takePicture"}
}
Dim request As Net.WebRequest = Net.WebRequest.Create(url)
request.Credentials = New Net.NetworkCredential(THETA_ID, THETA_PASSWORD)
Dim resp As Net.WebResponse = request.GetResponse()
End Function
See the line where is says:
End Function
Look in the line numbers margin; next to it there is a blank bar (mine is dark gray in my theme) - click in it to put a red dot:
End Function will go red too..
Then run your code and retrieve your image. The code will stop with a yellow bar pointing to End Function
Take a look at the bottom of VS - you'll either have an Autos window or a Locals window - either one will do. It will show the response object and you can drill into it like a tree, open the headers collection, have a look if anything in it contains the data you want.. It also thus tells you how to get the data you want out of it..
e.g. if I wanted the "Content-Disposition" value I could say resp.Headers("Content-Disposition") - AllKeys is showing me what available strings I can use to index the headers collection
Content-Disposition probably won't list a filename on its own - it'll be something more involved like "attachment; filename=someimage.jpg" so you'll need to pull the data you want out of it. Don't get your hopes up if this is a basic cam; it's unlikely to have any meaningful sort of filename. It might be IMG_0001 etc, if it's there at all - I think you should instead make your own name up, as you'll be able to put more info into it, it will be more meaningful than what you get from the cam (and if the cam doesn't send a filename you'll have to do it anyway)

OCR image with text using Leadtools + VB.Net to find Location/Coordinates of Specific text on Image

I could only find code using C#, but maybe someone can translate this into vb.net or assist with VB.NET code could that could help me. I'm only a beginner that worked with VB.net. I went to leadtools forums, but there is no example for what i want and most of the examples is written in only in C#
void HiliteWord(AnnContainer container, IOcrPage page, OcrWord word)
{
// Get bounds of word as LeadRectD
LeadRectD bounds = word.Bounds.ToRectangle(page.DpiX, page.DpiY).ToLeadRectD();
// Convert to annotation coordinates
bounds = container.Mapper.RectToContainerCoordinates(bounds);
// Create the annotation
AnnHiliteObject hilite = new AnnHiliteObject();
hilite.Points.Clear();
hilite.Points.Add(bounds.TopLeft);
hilite.Points.Add(bounds.TopRight);
hilite.Points.Add(bounds.BottomRight);
hilite.Points.Add(bounds.BottomLeft);
// Add to container
container.Children.Add(hilite);
}
As David said in his comments, you can convert c# to vb.net using an online converter. Also, just so you know, the LEADTOOLS SDK has chat, emails, and forums as support options if you need assistance with the SDK:
https://www.leadtools.com/support/supportoptions
I ran the above code in the converter that David linked and this was the output which is correct and will work in your application:
Private Sub HiliteWord(ByVal container As AnnContainer, ByVal page As IOcrPage, ByVal word As OcrWord)
Dim bounds As LeadRectD = word.Bounds.ToRectangle(page.DpiX, page.DpiY).ToLeadRectD()
bounds = container.Mapper.RectToContainerCoordinates(bounds)
Dim hilite As AnnHiliteObject = New AnnHiliteObject()
hilite.Points.Clear()
hilite.Points.Add(bounds.TopLeft)
hilite.Points.Add(bounds.TopRight)
hilite.Points.Add(bounds.BottomRight)
hilite.Points.Add(bounds.BottomLeft)
container.Children.Add(hilite)
End Sub

using Class TextToolStripSeparator

Hi Imm trying to use the Class TextToolStripSeparator, as provided here.
How to add informative text to menu strip separator in vb.net or C#
I am having dificulty implementing the solution. I have placed the classes in and have created a separator but I can't seem to figure out how to place the text. I am using a dynamicaly created ContextMenuStrip in a datagridview from a right click.
Dim menu As ContextMenuStrip = New ContextMenuStrip
Dim NewSep1 As New TextToolStripSeparator
menu.Items.Add(NewSep1)
menu.Show(Me, pt.X, pt.Y)
when I tryto add text like menu.Items.Add(NewSep1("-test-")) I get an error:
Error 1 Class 'myprog.TextToolStripSeparator' cannot be indexed because it has no default property.
What am I doing wrong?
It looks like you need to set the seperator's .Text property.
Dim NewSep1 As New TextToolStripSeparator
NewSep1.Text = "-test-"
menu.Items.Add(NewSep1)

How can I get a list of URLs of all images that appear on a webpage?

I'm trying to use VB.NET (2010) to get the absolute URLs of each image that appears on a specific webpage. So far, I've figured out how to get all of the URLs inside of an image tag, like so...
For Each SeparateImage As HtmlElement In WebBrowser1.Document.Images
ListBox1.Items.Add(SeparateImage.GetAttribute("src"))
Next
That works perfectly. But what I can't figure out is how to extract image URLs that appear within CSS styles. For example...
background-image:url('image.jpg');
Does anyone know of a simple way to do this? I would need to extract the image URLs not only from inline CSS code, but from external stylesheets as well.
I reckon that one way to do it would be to grab the source code of the entire HTML page page and related CSS stylesheet, and then parse out all of the image URLs using a bunch of string splits and/or regex. But that could get pretty complicated to figure out the correct absolute URL of each image, because of all the different possibilities of "relative" URL paths I may come across. For example...
background-image:url('image.jpg');
background-image:url('/image.jpg');
background-image:url('./image.jpg');
background-image:url('../image.jpg');
background-image:url('../otherdirectory/image.jpg');
So... it would be really nice if something like this existed...
For Each CSS_Style As HtmlElement In WebBrowser1.Document.Styles
ListBox1.Items.Add(CSS_Style.GetAttribute("background-image"))
Next
Does anyone know how I might be able to accomplish something like that? Or have any other ideas that don't involve mind numbing amounts of regex and logic? :)
Thanks in advance!
If you're specifically looking to avoid "mind numbing amounts of regex and logic", have you considered the HtmlAgilityPack ?
The following brief code should show all image URLs contained within the HTML downloaded from the bbc.co.uk website. It shouldn't be too hard to extend this code to parse the image links from any CSS files that are referenced from the HTML document.
Imports HtmlAgilityPack
Module Module1
Sub Main()
Dim mainUrl As String = "http://www.bbc.co.uk"
Dim doc As HtmlDocument
doc = New HtmlDocument()
Dim sourceString As String = New System.Net.WebClient().DownloadString(mainUrl)
doc.LoadHtml(sourceString)
For Each link As HtmlNode In doc.DocumentNode.SelectNodes("//img[#src]")
Dim linkAddress = GetAbsoluteUrl(link.Attributes("src").Value, mainUrl)
Console.WriteLine("Image: {0}", linkAddress)
Next
End Sub
'
Function GetAbsoluteUrl(partialUrl As String, baseUrl As String)
Dim myUri = New Uri(partialUrl, UriKind.RelativeOrAbsolute)
If (myUri.IsAbsoluteUri = False) Then
myUri = New Uri(New Uri(baseUrl), partialUrl)
End If
GetAbsoluteUrl = myUri
End Function
End Module