Cloud and Microsoft technologies enthusiast architect in Switzerland RSS 2.0
# Friday, October 19, 2012

<Caution>This post is based on the SharePoint 2013 Consumer Preview. Thus, behavior described here may change in the next release of the platform</Caution>

SharePoint 2013 is coming with a very nice feature which is the Managed Metadata Navigation, allowing us to define the navigation completely separated from the content or the physical pages. But, it has to be used with some attentions.

I found what could be interpreted as a bug in the SharePoint 2013 Consumer Preview and its new Managed Metadata Navigation. When a term has the same name as a subsite, the navigation to the page targeted by the term itself is fine, but for all the sub-terms, you get a “Page not found” message. The pictures below show that navigating to the “About” term is well going to the default page of the “About” subsite (i.e. /about/Pages/default.aspx), but when selecting an “About” sub-term, it does not display the /about/companyinformation/Pages/default.aspx page :

about_ok

sub_about_notfound

The structure of the content is the following :

sitestructure

And the metadata structure :

metadata

Even if, for the “About” term, I define a custom target page and explicitly specify /about/Pages/default.aspx , I still get the “Page not found” error.

The only way to solve this problem is to change the automatically assigned Friendly URL, AND, to change also the Target Page.

In fact, this is because there is a naming collision. /about, which is the Friendly URL associated with the “About” term is also the URL of the “About” sub-site. This is why the “About” term itself works.

It also works for the sub-term “About” / “Locations”, because the associated Friendly URL is /about/locations, which is also the name of the sub-site, leading to its default page. Unfortunately, the “Company Information” term is associated with the /about/company-information Friendly URL, which does not correspond to any sub-element of the /about site, which seems to take the precedence over the Friendly URL resolution and its Target Page. That explains that even if you specify a valid Target Page for the “Company Information” term, “Page not found” will still be displayed.

So, as written above, by changing the Friendly URL automatically associated to the “About” term to “aboutus” would only partially solve the issue. Indeed, /aboutus would remove the collision with the sub-site name, but would lead to an unexisting page. Changing also the Target Page, then, would completely work around this.

As a conclusion, be careful with the name you give to your site and the Friendly URL associated with the terms.

Friday, October 19, 2012 8:28:00 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
SP2013
# Tuesday, October 16, 2012

That is something we do almost every time when building workflows. Indeed, at some point in your process, you need to know who belongs to a SharePoint group and you wonder how to get this user’s list. Of course, there is a SharePoint API for that, but when working with Nintex, the only way, if you don’t want to code your custom action, is to use the SharePoint web services. And because it is something that is regularly needed, it made sense to have a “User Defined Action”, just for that. Not that it is difficult to do, but it is quite useful to have a single action that would return the list of user for a given group.

The SharePoint web service that can be used is located at /_vti_bin/usergroup.asmx . One of the method that can be called and which is especially interesting is GetUserCollectionFromGroup that has the following WSDL signature.

POST /_vti_bin/usergroup.asmx HTTP/1.1
Host: myserver
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "
http://schemas.microsoft.com/sharepoint/soap/directory/GetUserCollectionFromGroup"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserCollectionFromGroup xmlns="
http://schemas.microsoft.com/sharepoint/soap/directory/">
      <groupName>string</groupName>
    </GetUserCollectionFromGroup>
  </soap:Body>
</soap:Envelope>

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUserCollectionFromGroupResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/">
      <GetUserCollectionFromGroupResult>string</GetUserCollectionFromGroupResult>
    </GetUserCollectionFromGroupResponse>
  </soap:Body>
</soap:Envelope>

As it can be seen, the web method only needs a “groupName” string parameter and returns a user collection (in other words, an array of users, which is in fact a <Users><User></User></Users> element).

So, to create a useful UDA, the parameters that it should have are :

Parameter Type Direction
The Web Service URL Text Input
The Group Name Text Input
The XML Field you are interested in Text Input
The Collection of Users Collection Output

 

Parameters

The special thing here is the “XML Field your are interested in”. Because I didn’t want to limit the UDA to return either the login or the user first or last name, I decided to leave the decision to the user calling the UDA to choose which field to get in the collection. The format of the parameter is directly tied to the XML outputted by the web service :

<GetUserCollectionFromGroup xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/">
    <Users>
        <User ID="116"
                    Sid="S-1-5-21-2110917764-89557993-3811714100-1138"
                    Name="domain\annem"
                    LoginName="domain\annem"
                    Email="anne.m@domain.com"
                    Notes=""
                    IsSiteAdmin="False"
                    IsDomainGroup="False"
                    Flags="0" />
    </Users>
</GetUserCollectionFromGroup>

If you are interested in the name, the parameter should contain "@Name”, as it is an attribute of the User element. On the other side, if you are interested in the e-mail of the users, then it should contain “@Email”. The image below shows the activities being part of the UDA. Basically, 3 activities are needed : Call Web Service, Query XML, Regular Expression.

GetUsersFromGroupUDA

To configure the Call Web Service activity, enter the URL of the usergroup site’s web service, for example http://myserver/_vti_bin/usergroup.asmx. Enter the user name and password of an account that has the permissions to call the web service in the appropriate text box. A good practice would be to define a protected constant and to select it using the lock icon. Clicking on the Refresh button will list all the methods available from this web service, so, select the “GetuserCollectionFromGroup” one:

CallWebService

Once this is done, the parameters will be listed in the “Web service message” section. You can then replace the different web method arguments by the UDA’s parameters, such as “URL”, “groupName” and “Store result in”. You will end with the following configuration :

CallWebServiceFinal

The next activity, “Query XML” is there to parse the XML response we get from the web method, and to create the collection of users. In the case below, we use the semi-colon as a separator, and we use the “User Field” UDA’s parameter to match the correct attribute using an XSL, the bold part corresponding to the UDA’s parameter :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:p="http://schemas.microsoft.com/sharepoint/soap/directory/">
    <xsl:template match="p:GetUserCollectionFromGroup/p:Users">
        <xsl:for-each select="p:User">
        <xsl:value-of select="{WorkflowVariable:User Field}"/>;</xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Finally, the “Query XML” should look like :

QueryXML

The very last activity is “Regular Expression”. For a reason that I still have to understand, the collection generated by the “Query XML” activity and stored in the “ParsedGroupUsers” does not behave like a “correct” collection. This is why I use such “Regular Expression”, to split the “ParsedGroupUsers” variable using the semi-colon, and to store the result in the “User Collection” output parameter :

RegularExpression

That’s it !

Publish the User Defined Action and then use this UDA in your workflows.

Tuesday, October 16, 2012 2:06:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Nintex | SharePoint
# Wednesday, August 01, 2012

<Caution>This post is based on the SharePoint 2013 Consumer Preview. Thus, behavior described here may change in the next release of the platform</Caution>

LowMemoryError

While working on a SharePoint 2013, after several hours of uptime, the user interface showed me an error message when I wanted to save an item in a list : “The server was unable to save the form at this time. Please try again.” Looking at different possible causes, I found that the available memory was drastically low. Indeed, on this 8GB RAM front-end server virtual machine (the database is hosted on a second VM), only few megs were still available.

LowMemoryNoderunner

Then, in the “Processes” tab, I saw that the noderunner.exe process was eating a lot of memory. A quick tour on Google and I found this Marc Molenaar’s blog post about the noderunner.exe process.

I decided to give it a try and, as suggested in the post, I restarted the “SharePoint Search Host Controller” service. Same observation as Marc, the service took a long time to restart and a huge part of the memory was released. The good thing is that at the same time it solved my item-saving issue. The error disappeared.

To be sure this service restart was “solving” the issue, I worked again several hours, playing also with the search and when the VM got short in memory, the same error message was shown to me again.

Another side effect of this low-memory case occurs when browsing the Managed Metadata tree. I suddenly received constantly an “Unexpected response from server. The status code of response is ‘500’. The status text of response is ‘System.ServiceModel.ServiceActivationException’. Unfortunately, it was impossible to get out of this message loop, and the only way to get rid of it was to kill the Internet Explorer application.

Error500

Wednesday, August 01, 2012 10:01:23 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
SP2013
# Wednesday, July 18, 2012

Since couple of weeks, the Microsoft world was boiling and the recent announcements raised the level of excitement among the partners, developers or users. For the most recent events, it started by the Yammer’s acquisition by Microsoft, followed by the Windows Phone 8 announcement. Then, Windows 8 and the related devices, accompanied with the Surface tablet. And now, what many people were expecting since a while, the Office 2013 wave, including SharePoint 2013. Here, it is not only a wave like we had with the “Office 14 wave”, but a tidal wave should we say, with the release of the “Consumer Preview” of the products, introducing the “Modern Office” concept.

During the July 16th presentation, SharePoint 2013 was slightly mentioned, but the complete set of Office 2013 Consumer Preview was released, and following the #officepreview twits was amazing. At the same time, the NDA by which the closest communities were tied (like the MVPs) was lifted and a massive amount of information was released.

The install

So, during the event, I downloaded the SharePoint Server 2013 to start an install in a VM (2.1 GB), with 4 CPUs and 8GB of RAM. The first surprise came when I started the setup program, which directly had an “Install Prerequisites”, saving us from downloading the pre-requisites individually (if I remember well, the first versions of SharePoint 2010 didn’t have such shortcut). And fortunately, because the list of pre-requisites is quite big. Once the the pre-requisites were installed, the setup itself took around 20 minutes to install the beast. The configuration wizard is well-known too, as it looks like (if not the same) the one of 2010. Finally, it is the post-install wizard that starts and displays the first bits of the new SharePoint 2013 user interface.

defaultHomePagenewthemeHomePage

Quick Round

Once the install is done, the first site created, the new user interface using the Metro style is presented. To be honest, the default theme is not the one that is the most successful; it is really difficult to see what is part of the header, what is part of the current navigation and the content. So, the first operation I did is to go in the former “Site Action” menu which is now in the right of the top bar, in the “Site Settings” and to “Change the look”. Some themes are better than others to distinguish between the content and the navigation. In addition, for each theme (or look ?), it is possible to select a different color scheme, to change or remove the background image or the fonts used.

By default, the ribbon is hidden and to make it appearing, you have to click on one of the menu header. The ribbon will thus appear, “sliding” from the top of the page header. The current navigation didn’t change much, but a nice feature is the ability to modify the links of both the global navigation and the current navigation, using the “Edit Links” link, pretty convenient as it does not force you to “Top Link Bar” or the “Quick Launch” settings.

The user menu is quite simple now. Exit the “Sign in as a different user” or other items, in SharePoint 2013, only “About Me” leading you to your personal page and the social part of SharePoint and “Sign Out”. In the same area, the “Share” button allows you to invite others and assign permissions to them on the current page, “Follow” to have the current page appearing in your feeds, “Sync” to synchronize locally the content of your site, “Edit” which is a shortcut to the Page => Edit action, or the surprising “Focus on Content” button. This feature toggles between a view without any navigation and having only the content area on the screen, and the standard view of the SharePoint page. Why not….

ViewProperties

But, how to create a document library ? If you are not familiar (this means the first 15 minutes), you will desperately look for a “Create” button somewhere. Rather than that, going in the “Site Contents” enables you to “add an app”, which will proposes you the different types of lists or libraries you can create. Thus, I created a first library and uploaded a file in that library, which does not differ from the previous version of SharePoint. Where I am surprised again is regarding the usability of some features. For example, viewing the properties of a file, where before it was quick and needed only one click, in SharePoint 2013 it requires 2 clicks, each time on the “…” button. For such functionality, I would expect to have it directly in the context menu of the item. Let’s see if it stays like this in the final release, but maybe it worth some improvements in some cases.

The performance

performances

With SharePoint 2010, installing it on a VM with 4 CPUs and 8GB of RAM was quite ok for trying some things. Having SQL Server in the same VM was not that bad. Sometimes slow, but not that bad. Here with SharePoint Server 2013, I decided to install it on the same kind of machine, and after a bit of time, it became really slow. I connected the server to check the performances and, even if the CPUs were only used at several percentages, it was radically different with the memory. It is simple, less than 1GB was “free”, the main memory eaters were SQL Server and the Distributed Cache Service (AppFabric). This demonstrates that another level of requirements. Indeed, checking on the web, I found this article from Bjorn Furuknap and later, the hardware requirements from Microsoft, 24GB of RAM (yes, 24 !!) is recommended, this new release of SharePoint has a price… It is also true that during the install and the configuration, I selected all the services, this for sure plays a role. But, Visual Studio is not yet installed and I am wondering what kind of setup a developer will need to have a decent development environment.

This concludes my very first post for SharePoint 2013, and will follow other articles describing either the (new) features of the platform or what is new in terms of architecture and development on a regular basis. So, as SharePoint 2013, I am “working on it” Smile and thanks to stay tuned.

Wednesday, July 18, 2012 10:37:07 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
SP2013
# Saturday, June 09, 2012

This post is also published on The SharePoint Bar

Recently, I was called to troubleshoot and fix an issue on a SharePoint 2010 farm with a simple statement that not all the users were displayed in the people picker list. Indeed, some users were listed, some not, without having a clear common pattern that could lead to something like “they are not in a group with enough privileges” or anything similar.

The symptoms

A simple way to reproduce the issue was to open a “Library Permissions” or a “List Permissions” in the ribbon of any library or list and then to select “Check Permissions” in the ribbon. This will open a dialog from which a people picker can easily be opened.

imageimage

Now, when clicking on the address book button and looking for a specific user, it was not displayed and therefore not selectable. This user was existing in the Active Directory, and, after a bit of time of investigation, I also found that, on the Central Administration or in a completely fresh web application and site collection, the problem was not present. Thus, it was clear it was only one site collection that had the issue.

Resolution

The issue was caused by a restriction applied to the people picker. Indeed, it is possible to restrict the scope of the people picker to a specific OU (Organizational Unit) or to use a specific LDAP filter. Let’s illustrate this. In my Active Directory, I created 3 OU, in each of them I created a user :

imageimageimage

In the people picker, I have all the users :

image

Now, execute the following command, which applies the limitation to the site collection specified by the –url parameter :

stsadm -o setsiteuseraccountdirectorypath -url http://centaurus -path "OU=OU2,OU=OU1,DC=plab,DC=local"

The result is that you will limit the scope of the people picker to the OU2 within OU1 :

image

To check the state of the limitations, execute the command below :

stsadm -o getsiteuseraccountdirectorypath -url http://centaurus

The result will be :

<SiteUserAccountDirectoryPath>OU=OU2,OU=OU1,DC=plab,DC=local</SiteUserAccountDirectoryPath>

To simply remove any restriction, execute the following command :

stsadm -o setsiteuseraccountdirectorypath -url http://centaurus/ -path ""

This command has no PowerShell equivalent and is part of a set of others along with properties, dedicated to configure the people picker and that are listed below (from the TechNet article : http://technet.microsoft.com/en-us/library/gg602068.aspx) :

Property name Description
Peoplepicker-activedirectorysearchtimeout

Configures the timeout when a query is issued to Active Directory. The default timeout value is 30 seconds. For more information, see Peoplepicker-activedirectorysearchtimeout.

Peoplepicker-distributionlistsearchdomains

Restricts the search of a distribution list to a specific subset of domains. For more information, see Peoplepicker-distributionlistsearchdomains.

Peoplepicker-nowindowsaccountsfornonwindowsauthenticationmode

Specifies not to search Active Directory when the current port is using forms-based authentication. For more information, see Peoplepicker-nowindowsaccountsfornonwindowsauthenticationmode.

Peoplepicker-onlysearchwithinsitecollection

Displays only users who are members of the site collection when the Select People and Groups dialog box is used. For more information, see Peoplepicker-onlysearchwithinsitecollection.

Peoplepicker-peopleeditoronlyresolvewithinsitecollection

Displays only users who are members of the current site collection when the Check Names button is clicked. For more information, see Peoplepicker-peopleeditoronlyresolvewithinsitecollection: Stsadm property (SharePoint Server 2010).

Peoplepicker-searchadcustomfilter

Enables a farm administrator to specify a unique search query. For more information, see Peoplepicker-searchadcustomfilter.

Peoplepicker-searchadcustomquery

Permits the administrator to set the custom query that is sent to Active Directory. For more information, see Peoplepicker-searchadcustomquery.

Peoplepicker-searchadforests

Permits a user to search from a second one-way trusted forest or domain. For more information, see Peoplepicker-searchadforests.

Peoplepicker-serviceaccountdirectorypaths

Enables a farm administrator to manage the site collection that has a specific organizational unit (OU) setting as defined in the Setsiteuseraccountdirectorypath setting. For more information, see Peoplepicker-serviceaccountdirectorypaths.

 

This other TechNet article explains what are the other people picker configurations that can be done : http://technet.microsoft.com/en-us/library/gg602075.aspx

These different commands can be really useful to restrict the users that can be added in a site collection, based on OUs in the Active Directory. To enable this, the Active Directory should follow the security model of your SharePoint organization, as it is only possible to restrict to a single OU as it is not possible to specify several OUs.

And, finally, it has to be documented, as these different properties and commands are not available in the SharePoint user interface and this feature may not come to the mind of the administrators that would have to find out why they don’t find users in the SharePoint infrastructure.

Saturday, June 09, 2012 8:40:00 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
SharePoint
# Friday, March 23, 2012
VS11Beta

This post is also published on The SharePoint Bar

The 16th of February, Microsoft released the Beta version of the next Visual Studio development environment, called Visual Studio 11. I made a quick tour of it, and I wanted to see what will be new in this new version of Visual Studio. But, before going in the observations I made, I want to emphasize that it is still a Beta version of the tool. Things can change and what I am writing here will probably be wrong in the couple of next months, when the final release of Visual Studio will come out.

First, as for the previous version of VS, it exists in several editions : Ultimate, Premium, Professional and also the Express one for Windows 8.

The first thing that we can see is the user interface that completely changed, starting with the splash screen of the installation and also the different screens during the setup wizard.

VS11SplashScreen

This is confirmed when we open the tool, all is in gray and black. People will love it or will hate it, but personally, in a development tool, I am not fan of having a Christmas tree with a lot of different colors.

In this post, I will focus on the SharePoint development aspects of Visual Studio and I will not go in too much details, keeping this tour at a high level.

So, when we want to create a new SharePoint project, we can see that it is no longer possible to develop for SharePoint 2007. Indeed, the SharePoint 2007 project template is not available. Maybe it will come in the final release, but with SharePoint vNext coming (we still not know whether it will be SharePoint 15, SharePoint 2013 or even something else), I doubt that it will be added. As it is shown in the picture below, the number of templates is limited to the strict necessary : an empty SharePoint project, importing a solution package, importing a reusable workflow, or starting a Silverlight or a visual web part projects. The Silverlight web part project is new, but I will come back to it further in this post.

NewSPProject

The new project creation wizard has not changed and it is still asking whether you want to create a sandbox or a farm solution, and also where is your SharePoint installation. What has not changed, or at least what I saw on my setup, is that you still cannot develop for SharePoint if you don’t have it installed on your development machine.

NewSolutionWizard

Once your project is created and you want to create a new item, you have the similar choices as with the previous version of Visual Studio, only 3 types have been added : Silverlight web part, site column and site definition. Let’s focus on these three items a bit more and also on the List and the Content Type items, starting with the last one.

NewProjectItem

Content Types

When you want to add a Content Type, it starts with the wizard, asking you from which existing content type you want yours to inherit. Once you have selected the parent content type, you will have a pretty nice surprise. There is now a visual editor for the content type, split in two tabs : Columns and Content Type. The first tab, Columns enables you to select the site columns to use, giving you the type of the column at the same time, and the possibility to specify if a value is required. The second tab, Content Type, is used to define the name of the content type, in which group to send it and few other settings. Of course, if you want to go in the CAML definition, you can still open the .xml file.

NewCTCTColumnsTabCTInfo

List

Even if the List project item was already existing in VS2010, Microsoft added a visual designer to it. It is now possible to select the site columns, the content types and also to define the views for the list. A great improvements for the developers, in my opinion.

ListColumnsTabListViewsTabListCTSelection

Site Definition

Site definition is a new project item coming with VS11 and what it mainly does is to create the item with the two necessary files : onet.xml and the webtemp file. That said, you still have to manually edit the files.

Silverlight web part

The interesting thing with this new project item is that it creates in reality two items : a Silverlight project containing then elements like the xaml files, and and Silverlight web part project item, which contains nothing more than the Elements.xml and the .webpart files.

NewSLWP

At the end, VS11 is promising for the SharePoint developments, but we should not expect too much from the next version. Some really nice improvements are already there, maybe some new ones will join in the final release, but again, this was just a first lap around the functionalities offered by the beta version of Visual Studio 11. I will come back on specific topics in several other posts in a near future.

Stay tuned !

Friday, March 23, 2012 8:12:00 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Programming | SharePoint
# Wednesday, March 14, 2012

On the initiative of my colleague and friend Julien, a new SharePoint community blog has been opened : The SharePoint Bar. Indeed, working (and sometimes struggling) daily with SharePoint, we often said “let’s open a bar”. So, we did it, the bar is open.

The goal is to have a shared platform on which several consultants will publish posts with their experiences, hints or solutions they had with the SharePoint box. From my side, the SharePoint-related posts from my personal blog will also be published on The SharePoint Bar.

As a first step, a calendar of events and conferences was opened and if you want to share one of them that is not yet published, feel free to drop an e-mail to yvespeneveyre.sp@gmail.com . The rules that apply are also written in that blog post.

Wednesday, March 14, 2012 10:39:16 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Blog Life | SharePoint
# Tuesday, February 21, 2012

Developing ClickOnce WPF application, it was needed to implement a spell checker for the different text boxes of the application. Our development environment was Windows 7, and using the .NET Framework 4 both the framework and the OS in english. The problem appeared when we tested the application, where the spell check in french or other non-english languages was not working at all. After several readings on the web and other experimentations using a quick-and-dirty application, I would like to give my findings here.

Basically, the XAML of my testing application is the one below :

<Window x:Class="TestApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <RichTextBox Margin="0,52,0,65" Name="rtbText" SpellCheck.IsEnabled="True" Language="fr">
            <FlowDocument>
                <Paragraph>
                    The quick brown fox jumps over the lazy dog
                    Le renard brun rapide saute sur le chien paresseux
                    Die schnelle braune Fuchs springt über den faulen Hund
                </Paragraph>
            </FlowDocument>
        </RichTextBox>
        <Button Content="FR" Height="23" HorizontalAlignment="Left" Name="btnFR" VerticalAlignment="Top" Width="30" Click="btnFR_Click" />
        <Button Content="EN" Height="23" HorizontalAlignment="Left" Margin="36,0,0,0" Name="btnEN" VerticalAlignment="Top" Width="30" Click="btnEN_Click" />
        <Button Content="Save" Height="23" HorizontalAlignment="Left" Margin="428,0,0,0" Name="btnSave" VerticalAlignment="Top" Width="75" Click="btnSave_Click" />
        <RichTextBox Language="fr" Margin="0,264,97,0" Name="rtbSwitch" SpellCheck.IsEnabled="True">
        </RichTextBox>
        <Button Content="DE" Height="23" HorizontalAlignment="Left" Margin="72,0,0,0" Name="btnDE" VerticalAlignment="Top" Width="30" Click="btnDE_Click" />
    </Grid>
</Window>

Which gives the window below :

image

When one of the upper-left button is clicked, a code similar to the one below is executed :

private void btnEN_Click(object sender, RoutedEventArgs e)
{
  TextRange tr = new TextRange(rtbText.Document.ContentStart, rtbText.Document.ContentEnd);
  tr.ApplyPropertyValue(FlowDocument.LanguageProperty, "en");
}

 

Basically, it takes the whole content of the Rich Text Box and change the “Language” property to the language in which the spell check has to be done.

Now, the problem is that if you compile the application on the .NET Framework 4, it will not work........unless the corresponding language packs of the Framework. They are all available on the Microsoft Download Center. Indeed, according to the table below, as soon as you use the .NET Framework 4, the language packs have to be installed, whereas if you use the .NET Framework 3.5 SP1, it depends on the platform on which the application is running. On Windows Vista and Windows 7, no need to install the language packs, for Windows XP, they are needed :

  Windows XP Windows Vista Windows 7
.NET 3.5 SP1 Language Packs Needed No need for the Language Packs No need for the Language Packs
.NET 4 Language Packs Needed Language Packs Needed Language Packs Needed

 

So, reverting back to the .NET Framework 3.5 made the spell checking to work.

That would be it, but, when typing new text, the spell check was not working and the reason can be found in the XAML extract of the Rich Text Box (“Save” button). When switching to english, I supposed that the new text would be checked against the english language, which is completely wrong. The XAML below shows the text right after the switch to the english language :

<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="fr" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="Text" NumberSubstitution.Substitution="AsCulture" FontFamily="Segoe UI" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="12" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0"><Paragraph><Run xml:lang="en">The quick brown fox jumps over the lazy dog Le renard brun rapide saute sur le chien paresseux Die schnelle braune Fuchs springt über den faulen Hund</Run></Paragraph></Section>

The interesting part is the last <Run> element, that contains an xml:lang=”en” attribute, specifying that the enclosed text is in english. When some text is entered, the corresponding XAML becomes the following :

<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="fr" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="Text" NumberSubstitution.Substitution="AsCulture" FontFamily="Segoe UI" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="12" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0"><Paragraph><Run xml:lang="en">The quick brown fox jumps over the lazy dog Le renard brun rapide saute sur le chien paresseux Die schnelle braune Fuchs springt über den faulen Hund</Run><Run xml:lang="fr-ch"> another text </Run></Paragraph></Section>

Surprisingly, the last <Run> element is now using the xml:lang=”fr-ch” language. What happens ? It simply takes the input language of the keyboard. It also means that if you want to change the on-the-fly spell check, the input language has to be changed. As an example, the click event handler written above becomes :

private void btnEN_Click(object sender, RoutedEventArgs e)
{
  TextRange tr = new TextRange(rtbText.Document.ContentStart, rtbText.Document.ContentEnd);
  tr.ApplyPropertyValue(FlowDocument.LanguageProperty, "en");
  InputLanguageManager.Current.CurrentInputLanguage = new CultureInfo("en-us");
}

At the last line of the event handler, the keyboard input language is changed and you will notice it in the tray bar, if displaying the current input language, that the locale has changed. Very important, the culture has to absolutely match an input language installed in the regional settings.

Changing the input language is not the best way as it changes the layout of the keyboard (for example, switching to en-us a fr-ch keyboard layout will lose the accented characters) and so far I have not yet found a way to workaround this.

Tuesday, February 21, 2012 11:12:20 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Programming
Google Cloud Platform Certified Professional Cloud Architect
Ranked #1 as
French-speaking SharePoint
Community Influencer 2013
Navigation
Currently Reading :
I was there :
I was there :
I was exhibiting at :
I was there :
I was a speaker at :
I was a speaker at :
I was a speaker at
(January 2013 session):
I was a speaker at :
I was a speaker at :
United Nations (UN) SharePoint Event 2011
I was a speaker at :
I was there !
I was there !
I was there !
I was there !
Archive
<October 2012>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2020
Yves Peneveyre
Sign In
Statistics
Total Posts: 289
This Year: 1
This Month: 0
This Week: 0
Comments: 19
Themes
Pick a theme:
All Content © 2020, Yves Peneveyre
DasBlog theme 'Business' created by Christoph De Baene (delarou)