Reset a boolean field in InfoPath

Want to reset a boolean field, with an initial value of (empty), to its initial state? Read on!

The initial value of an ’empty’ boolean field in InfoPath:

<my:boolean xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:nil=”true“></my:boolean>

After you select one of the radiobuttons the textnode of the element gets a value indicating whether true or false was selected:

<my:boolean xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“>true</my:boolean>

The important thing to notice here, is the removal of the attribute ‘xsi:nil=”true”‘. If you want to reset this field to its initial state then you need to do two things: remove the textnode and recreate the ‘xsi:nil’ attribute.

Let’s add a button (resetBtn) to the form and give it some code-behind:

public void resetBtn_Clicked(object sender, ClickedEventArgs e)
{
    resetNode("/my:mijnVelden/my:boolean");
}
private void resetNode(string xpath)
{
    XPathNavigator xnMain = MainDataSource.CreateNavigator();
    XPathNavigator node = xnMain.SelectSingleNode(xpath, NamespaceManager);
    XPathNavigator textNode = node.SelectSingleNode("text()");
    if (textNode != null)
    {
        textNode.DeleteSelf();
        node.CreateAttribute("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
    }
}

And that’s about it.

Download an example here: InfoPath Form Template – resetBoolean

Expose a static XSD in a dynamic WSDL

When you use xsd.exe to generate classes from an XML Schema Definition, then you will probably lose details regarding that schema (eg. minOccurs & maxOccurs constraints). If you then expose the generated classes through a service, the XSD used will differ from the one you originally used.

If the XSD you use is part of some standard, this will impose a problem. We resolved this by using an IEndpointBehavior and IWsdlExportExtension, which will dynamically inject our static XSD into the WSDL. The main benefit of this approach is that the dynamic part of the WSDL (operations etc.) will still be intact, as opposed to exposing an external metadata file.

sgen.exe & multiple types

If you have ever used sgen.exe to generate/precompile serialization-assemblies, I’m sure you are surprised by the fact that it doesn’t allow you to specify multiple types to generate the classes for. After trying to find an alternative (and failed to do so), I decided to see if it’s possible to disassemble and alter sgen’s sourcecode. It is surprisingly simple. In this post, I’ll guide you through the steps I have taken.

First, download and install Reflector. Then locate sgen.exe. On my laptop, with VS2010 installed, it’s located at C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin. Open sgen.exe in Reflector, right-click sgen and choose ‘Export’. This will disassemble the executable and export all it’s content including a .csproj file; very convenient.

We now need to alter sgen’s source at a couple locations.

1. there is a fixed, absolute path to the key file originally used to sign the assembly. From the AssemblyInfo.cs remove:

[assembly: System.Reflection.AssemblyKeyFile(@"f:\dd\Tools\devdiv\FinalPublicKey.snk")]
[assembly: System.Reflection.AssemblyDelaySign(true)]

If desired, sign the assembly with your own key file.

2. in the file CommonResStrings.cs the class Assembly is used, but the corresponding using statement is missing. Add the using statement:

using System.Reflection;

3. next up is SgenTool\Sgen.cs. In the method ‘Run’ change:

~ line #356
string typeName = null;

to:

List<string> typeNames = new List<string>();
~ line #457
else if (this.ArgumentMatch(arg, "type"))
{
    typeName = str6;
}

to

else if (this.ArgumentMatch(arg, "type"))
{
    typeNames.Add(str6);
}
~ line #484
this.GenerateAssembly(typeName, assemblyName, list, proxyOnly, silent, warnings, debug, keepFiles, force, codePath, compilerOptions, parsableerrors);

to

this.GenerateAssembly(typeNames, assemblyName, list, proxyOnly, silent, warnings, debug, keepFiles, force, codePath, compilerOptions, parsableerrors);

Then change the signature of the GenerateAssembly method into:

~ line #109
private void GenerateAssembly(List<string> typeNames, string assemblyName, ArrayList references, bool proxyOnly, bool silent, bool warnings, bool debug, bool keepFiles, bool force, string codePath, string compilerOptions, bool parsableerrors)
~ line #124
if (typeName == null)
{
    types = assembly.GetTypes();
}
else
{
    Type type = assembly.GetType(typeName);
    if (type == null)
    {
        Console.Error.WriteLine(FormatMessage(parsableerrors, false, Res.GetString("ErrorDetails", new object[] { Res.GetString("ErrLoadType", new object[] { typeName, assemblyName }) })));
    }
    types = new Type[] { type };
}

to

if (typeNames.Count == 0)
{
    types = assembly.GetTypes();
}
else
{
    List<Type> typeList = new List<Type>();
    foreach (string typeName in typeNames)
    {
        Type type = assembly.GetType(typeName);
        if (type == null)
        {
            Console.Error.WriteLine(FormatMessage(parsableerrors, false, Res.GetString("ErrorDetails", new object[] { Res.GetString("ErrLoadType", new object[] { typeName, assemblyName }) })));
        }
        else
        {
            typeList.Add(type);
        }
    }
    types = typeList.ToArray();
}

And finally

~ line #216
else if (typeName == null)
{
    if (warnings)

to

else if (typeNames.Count == 0)
{
    if (warnings)

That’s it! Compile and enjoy your new multi-type-capable sgen.exe! You simply need to provide multiple /t command-line arguments.

note: I’ve written this post out-of-the-office and it’s a little untested. But I’m pretty sure, these are the steps I’ve did. If something’s not working for you, let me know and I’ll see what I can do. Also I’m not very thrilled about the current code-formatting in this post; I might fix that someday

How to install Chameleon-2.0

Installing Chameleon is very simple: RTFM!

But since this is hard for some people, myself included, you end up googling for it or asking others on a forum. To avoid that, I’ve decided to put up the few commands necessary to install this bootloader; which are easily found in the README that comes with the downloaded package.

First you need to find out on which drive (& partition) you want to install Chameleon. You can do this using Terminal or through the Disk Utility app. In this post I’m assuming we’re using the Terminal.

At the prompt type: diskutil list. This will provide a list with drives & partitions with their associated identifier. Locate your target. Let’s say that your target is disk0s2.

Next step is the actual installing of Chameleon (replace the disk- and partition-number with your own).

– Install boot0 to the MBR:
sudo fdisk -f boot0 -u -y /dev/rdisk0
– Install boot1h to the partition’s bootsector:
sudo dd if=boot1h of=/dev/rdisk0s2
– Install boot to the partition’s root directory:
sudo cp boot /

That’s it. You’re good to go. Now add /Extra and /Extra/Extensions folder and supply a com.apple.Boot.plist, smbios.plist and the appropriate .kext files.