<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://communities.bentley.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>[CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock</link><description>TextBlock Class 
 From the DgnPlatformNet help document: In the TextBlock DOM, this is the master object that represents a piece of text as a whole, and is the primary high-level object used to deal with multi-line, formatted text (and is also generally</description><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/745044?ContentTypeID=1</link><pubDate>Wed, 07 Dec 2022 10:43:35 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:ffa88eff-9ab5-478f-ac8e-377c0cfd01fd</guid><dc:creator>Jan Šlegr</dc:creator><description>&lt;p&gt;Hi Jon,&lt;/p&gt;
[quote userid="2269" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/744603"]With .NET it&amp;#39;s not possible to navigate to each text element using the TextBlock API.[/quote]
&lt;p&gt;I am outside office, so I am not able to check my code archive, but I disagree it&amp;#39;s not possible to navigate text elements. As far as I remember, using carets it&amp;#39;s possible to analyze complete text and to find required piece of text.&lt;/p&gt;
&lt;p&gt;I see no problem to use carets only, but sometimes it requires to write a bunch of own code. But there are classes like paragraph iterator available, that makes navigating a bit simpler (but in fact the iterator is only a wrapper around, again, using carets).&lt;/p&gt;
[quote userid="2269" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/744603"]In contrast, C++ lets us find paragraphs and runs.[/quote]
&lt;p&gt;I am not sure without consulting API and assemblies delivered with MicroStation, but I am pretty sure all important classes are available for a long time in API, including Run, RunIterator, Paragraph or ParagraphIterator (plus related properties classes).&lt;/p&gt;
&lt;p&gt;With regards,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; Jan&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/744603?ContentTypeID=1</link><pubDate>Mon, 05 Dec 2022 11:46:06 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:6c981350-d90d-47b6-a47c-9ecaa76eea91</guid><dc:creator>Jon Summers</dc:creator><description>[quote userid="2473" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/744592"] I was always able to find solution for any task[/quote]
&lt;p&gt;There are examples above.&amp;nbsp;&amp;nbsp; They show text nodes that contain text elements.&amp;nbsp; With .NET it&amp;#39;s not possible to navigate to each text element using the TextBlock API.&amp;nbsp; In contrast, C++ lets us find paragraphs and runs.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/744592?ContentTypeID=1</link><pubDate>Mon, 05 Dec 2022 10:52:04 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:d235052a-111f-45b2-82c2-53f7418d7f49</guid><dc:creator>Jan Šlegr</dc:creator><description>&lt;p&gt;Hi Jon,&lt;/p&gt;
&lt;p&gt;what exactly do you miss in available API? I did not do any detail comparison, but as far as I remember, I was always able to find solution for any task I implement, regardless to create or query/modify text.&lt;/p&gt;
&lt;p&gt;The only missing API I know are Text Fields.&lt;/p&gt;
&lt;p&gt;Regards,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; Jan&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/744589?ContentTypeID=1</link><pubDate>Mon, 05 Dec 2022 10:35:09 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:f0aa13bf-b450-401d-8afa-4fdcdfd343af</guid><dc:creator>Jon Summers</dc:creator><description>&lt;p&gt;Bump!&lt;/p&gt;
[quote userid="2269" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/735921"]Given that the .NET API appears to be incomplete, it is impossible for a developer to fully utilise the TextBlock API for interrogating elements that contain text[/quote]
&lt;p&gt;What plans are there to implement the .NET TextBlock in full?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/735921?ContentTypeID=1</link><pubDate>Mon, 10 Oct 2022 13:39:50 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:a926933f-4355-4a35-98e3-1721eb9ab74d</guid><dc:creator>Jon Summers</dc:creator><description>&lt;p&gt;From the DgnPlatformNet help document about TextBlock: &lt;cite&gt;In the TextBlock DOM, this is the master object that represents a piece of text as a whole, and is the primary high-level object used to deal with multi-line, formatted text (and is also generally recommended for any text, regardless of complexity)&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Given that the API appears to be incomplete, it is impossible for a developer to fully utilise the TextBlock API for interrogating elements that contain text.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is there a timetable to improve the API?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Who is responsible for the TextBlock API?&lt;/li&gt;
&lt;/ul&gt;
[quote userid="2163" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/734763"]Let me know if you need something more[/quote]
&lt;p&gt;Someone needs to extend the TextBlock API so that its implementation matches its specification.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/734787?ContentTypeID=1</link><pubDate>Sat, 01 Oct 2022 07:57:56 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:7da3eb6f-e6bc-4c59-998a-b55470291349</guid><dc:creator>Jon Summers</dc:creator><description>[quote userid="2163" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/734763"]...look to the &amp;quot;Text&amp;quot; help topic...[/quote]
&lt;p&gt;There is no &lt;em&gt;Text&lt;/em&gt; help topic in the &lt;em&gt;DgnPlatformNet&lt;/em&gt; document, but it is in the C++ &lt;em&gt;MicroStationAPI&lt;/em&gt; help document.&lt;/p&gt;
&lt;p&gt;As &lt;a title="Jan &amp;Scaron;legr" href="/members/ff247d2f_2d00_7ed5_2d00_451a_2d00_b5b2_2d00_a6fc5dbbf405" rel="noopener noreferrer" target="_blank"&gt;Jan&lt;/a&gt; so often recommends, I should have examined the &lt;em&gt;MicroStationAPI&lt;/em&gt; .&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/734785?ContentTypeID=1</link><pubDate>Sat, 01 Oct 2022 06:15:32 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:a7429736-bc7a-45d3-af13-44f7187899d1</guid><dc:creator>Jon Summers</dc:creator><description>[quote userid="2163" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock/734763"]The following are a few .NET unit tests I found[/quote]
&lt;p&gt;Thanks, but those are mostly about text creation, apart from one or two uses of &lt;em&gt;text parts&lt;/em&gt; to find a simple text string.&lt;/p&gt;
&lt;p&gt;A type 17 text element is easy to navigate, because it contains a single string, which &lt;code&gt;TextBlock.ToString()&lt;/code&gt; provides.&amp;nbsp; I&amp;#39;m asking for hints about navigating a more complex type 7 text element, such as a text node that contains multiple text elements...&lt;/p&gt;
&lt;pre&gt;Line 1
Line 2
Line 3&lt;/pre&gt;
&lt;p&gt;Or has different text styles for concatenated strings...&lt;/p&gt;
&lt;pre&gt;Word 1 &lt;span style="color:maroon;"&gt;Word 2&lt;/span&gt; &lt;span style="color:dodgerblue;"&gt;&lt;big&gt;Word 3&lt;/big&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;(You can create either of the above using MicroStation&amp;#39;s text editor)&lt;/p&gt;
&lt;p&gt;For example...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do I get a &lt;em&gt;run&lt;/em&gt; or &lt;em&gt;paragraph&lt;/em&gt; for &lt;em&gt;Line 2&lt;/em&gt; or &lt;em&gt;Word 3&lt;/em&gt;?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;How do I find the text style applied to &lt;em&gt;Word 2&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;How do I get the origin of text elements &lt;em&gt;Line 1&lt;/em&gt;, &lt;em&gt;Line 2&lt;/em&gt; and &lt;em&gt;Line 3&lt;/em&gt;?&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: [CONNECT Update 17 C#] Navigating a TextBlock</title><link>https://communities.bentley.com/thread/734763?ContentTypeID=1</link><pubDate>Fri, 30 Sep 2022 20:03:12 GMT</pubDate><guid isPermaLink="false">6dad98f5-dbc9-4c4d-a9ba-e9da8dc6aa8e:15def430-c888-4fea-b262-715ac09533c1</guid><dc:creator>Robert Hook</dc:creator><description>&lt;p&gt;Hi &lt;a href="/members/de0601d9_2d00_ca2e_2d00_4005_2d00_a7b3_2d00_982abaee9aeb"&gt;Jon Summers&lt;/a&gt;,&lt;/p&gt;
[quote userid="2269" url="~/products/programming/microstation_programming/f/microstation-programming---forum/236383/connect-update-17-c-navigating-a-textblock"]&lt;p&gt;Where is the &lt;cite&gt;Text module documentation&lt;/cite&gt;?&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;[/quote]
&lt;p&gt;My modified version of those few words (to clarify) would be: Text (help module) documentation.&lt;/p&gt;
&lt;p&gt;Indicating to look to the &amp;quot;Text&amp;quot; help topic for an Overview of the Text (many forms) leading into the TextBlock API relationship details.&lt;/p&gt;
&lt;p&gt;The following are a few .NET unit tests I found, where you will need to modify any calls to Assert directly or simply ignore or handle each method or result accordingly.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Code Snip:&amp;nbsp;CreateTextElementTest&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void CreateTextElementTest()
{

    //Create a text block.
    TextBlock textBlock = new TextBlock(m_tbProps, m_pProps, m_runProps, m_defaultModel);
    textBlock.AppendText(&amp;quot;Simple Text&amp;quot;);

    //CREATE text element.
    TextElement textElement = (TextElement)TextHandlerBase.CreateElement(null, textBlock);
    Assert.AreEqual(StatusInt.Success, textElement.AddToModel());
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Code Snip:&amp;nbsp;CreateTextElementFromTextBlock&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;/// &amp;lt;summary&amp;gt;
/// Helper method for creating text element.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;model&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&amp;quot;textBlock&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
protected string CreateTextElementFromTextBlock(ref DgnModel model, ref TextBlock textBlock)
{
    //CREATE text element.
    TextHandlerBase textElement = TextHandlerBase.CreateElement(null, textBlock);
    Assert.IsNotNull(textElement);
    Assert.AreEqual(true, textElement.IsTextElement);

    return (textElement.GetTextPart(textElement.GetTextPartIds (new TextQueryOptions()) [0])).ToString();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Code Snip:&amp;nbsp;TextElement_CRUD_Test&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void TextElement_CRUD_Test()
{

    //Create a text block.
    TextBlock textBlock = new TextBlock (m_tbProps, m_pProps, m_runProps, m_defaultModel);
    textBlock.AppendText(&amp;quot;Simple Text&amp;quot;);

    //CREATE text element.
    TextElement textElement = (TextElement)TextHandlerBase.CreateElement(null, textBlock);
    textElement.AddToModel();
    Assert.IsNotNull(textElement);
    Assert.AreEqual(true, textElement.IsTextElement);
    Assert.AreEqual(&amp;quot;Text&amp;quot;, textElement.TypeName);

    //READ: We know this model contains a single text element.
    {
        //Read from current element.
        foreach (TextPartId tId in textElement.GetTextPartIds (new TextQueryOptions()))
        {
            TextBlock tBlock = textElement.GetTextPart(tId);
            Assert.IsNotNull(tBlock);
            Assert.AreEqual (&amp;quot;Simple Text&amp;quot;, tBlock.ToString ());
        }
    }

    {
        //Read from model.
        foreach (Element element in m_defaultModel.GetGraphicElements())
        {
            if (element.TypeName.Equals(&amp;quot;Text&amp;quot;))
            {
                TextElement textEeh = (TextElement)element;
                foreach (TextPartId tId in textEeh.GetTextPartIds (new TextQueryOptions()))
                {
                    TextBlock tBlock = textEeh.GetTextPart(tId);
                    Assert.IsNotNull(tBlock);
                    Assert.AreEqual (&amp;quot;Simple Text&amp;quot;, tBlock.ToString ());
                }
            }
            else
                Assert.Fail(&amp;quot;This model should contain only one text element&amp;quot;);
        }
    }

    //UPDATE text.
    TextEdit tEdit = textElement.AsTextEdit();

    TextPartIdCollection textParts = tEdit.GetTextPartIds (new TextQueryOptions());
    Assert.AreEqual(1, textParts.Count);
    TextPartId partId = textParts[0]; //We have confirmed that it contains one text part id.
    TextBlock textBlock2 = tEdit.GetTextPart(partId);
    Assert.AreEqual(false, textBlock2.IsEmpty);
    textBlock2.Remove(textBlock2.CreateStartCaret(), textBlock2.CreateEndCaret());
    Assert.AreEqual(true, textBlock2.IsEmpty);
    textBlock2.AppendText(&amp;quot;This is updated text&amp;quot;);
    Assert.AreEqual(false, textBlock2.IsEmpty);
    Assert.AreEqual(TextReplaceStatus.Success, tEdit.ReplaceTextPart(partId, textBlock2));
    tEdit.ReplaceInModel(textElement);
    Assert.AreEqual(StatusInt.Success, m_dgnFile.ProcessChanges(DgnSaveReason.ApplicationInitiated));

    //READ again: We know this model contains a single text element.
    {
        //Read from current element.
        foreach (TextPartId tId in tEdit.GetTextPartIds (new TextQueryOptions()))
        {
            TextBlock tBlock = tEdit.GetTextPart(tId);
            Assert.IsNotNull(tBlock);
            Assert.AreEqual (&amp;quot;This is updated text&amp;quot;, tBlock.ToString ());
        }
    }

    {
        //Read from model.
        foreach (Element element in m_defaultModel.GetGraphicElements())
        {
            if (element.TypeName.Equals(&amp;quot;Text&amp;quot;))
            {
                TextElement textEeh = (TextElement)element;
                foreach (TextPartId tId in textEeh.GetTextPartIds (new TextQueryOptions()))
                {
                    TextBlock tBlock = textEeh.GetTextPart(tId);
                    Assert.IsNotNull(tBlock);
                    Assert.AreEqual (&amp;quot;This is updated text&amp;quot;, tBlock.ToString ());
                }
            }
            else
                Assert.Fail(&amp;quot;This model should contain only one text element&amp;quot;);
        }
    }

    TextElement elemToDelete = null;

    //Read from model.
    foreach (Element element in m_defaultModel.GetGraphicElements())
    {
        if (element.TypeName.Equals(&amp;quot;Text&amp;quot;))
        {
            elemToDelete = (TextElement)element;
        }
    }

    //We are sure that a text element exist in model.
    Assert.IsNotNull(elemToDelete);

    //DELETE:
    Assert.AreEqual(StatusInt.Success, textElement.DeleteFromModel());
    Assert.AreEqual(StatusInt.Success, m_dgnFile.ProcessChanges(DgnSaveReason.ApplicationInitiated));

}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Let me know if you need something more.&lt;/p&gt;
&lt;p&gt;HTH,&lt;br /&gt;Bob&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>