Martijn's blog - E-Commerce, EAI, BizTalk and .NET

2006/11/03

WPF - Writing an IMultiValueConverter (update)

What I didn't realize in the previous blog entry regarding the subject was the fact that binding to a DependencyProperty and performing a string.Format blindly could lead to weird results, e.g.:
<TextBlock>
 <TextBlock.Text>
  <MultiBinding 
        Converter="{StaticResource StringFormatterConverter}" 
        ConverterParameter="{}{0}, {1}">
   <Binding Path="Customer.Lastname" />
   <Binding Path="Customer.Firstname" />
  </MultiBinding>
 </TextBlock.Text>
</TextBlock>

Could convert to "DependencyProperty.UnsetValue, DependencyProperty.UnsetValue" The solution is pretty simple:
bool argumentsAreNullOrEmpty = true;

// Check whether all values are null or unset.
foreach (object value in values)
{
 if (value != null && value != DependencyProperty.UnsetValue)
 {
  argumentsAreNullOrEmpty = false;
  break;
 }
}

// If we have all empty or null arguments, we do nothing.
if (argumentsAreNullOrEmpty)
{
 return Binding.DoNothing;
}

Happy WPFing!

2006/11/02

CAB: load your modules from your App.Config

In CAB, there's a 'special voodoo magic' file which defines which modules are to be loaded in the IoC process. The file is called ProfileCatalog.xml by default.

We're currently using CAB in combination with an XBAP application. This leads to deployment issues, as ProfileCatalog.xml will be deployed in to a folder called Data by default and the modules configured in the file cannot be located. You can work around this issue, but I took the issue as an opportunity to replace the default implementation of IModuleEnumerator in CAB with my own.

My implementation looks at the App.Config file for it's modules. All that's needed to use the new enumerator is to configure it:
<configSections>
 <section 
  name="SolutionProfile" 
  type="BankTellerModule.Services.ModulesSection, BankTellerModule" />
 <section 
  name="CompositeUI" 
  type="Microsoft.Practices.CompositeUI.Configuration.SettingsSection, Microsoft.Practices.CompositeUI" />
</configSections>

<CompositeUI>
 <services>
  <add
   serviceType="Microsoft.Practices.CompositeUI.Services.IModuleEnumerator, Microsoft.Practices.CompositeUI"    instanceType="BankTellerModule.Services.ConfigurationModuleEnumerator, BankTellerModule" />
 </services>
</CompositeUI>

<SolutionProfile>
 <Modules>
  <add assemblyFile="BankTellerModule.dll" />
 </Modules>
</SolutionProfile>

The code for this behaviour will be available here in a few hours...

ClickOnce deployment of XBAP application to remote IIS

To ensure you don't encounter the issues we encountered, make sure you set the option "Rename all application files using the .deploy file extension".
You can find the option under Project properties -> Publish -> Options.

If you don't use this option and your IIS is hardened, as it should be, you'll see your assemblies being rejected (404.2 return code in you W3 log files). The .2 subcode means the server is not allowed to serve .dll files.

The deployment renames the files from e.g. BankTellerModule.dll -> BankTellerModule.dll.deploy. This ensures the files get served by IIS. Locally, the files are stored in C:\Documents and Settings\<user account>\local Settings\Apps\2.0 and renamed back to .dll.

ClickOnce publishing XBAP applications and F5 debugging not working

Some times, when you publish an XBAP application using ClickOnce, you cannot debug the same application afterwards using F5. This is due to a change to the project settings (debug tab). The extension is removed from the command-line argument to PresentationHost.exe (-debug .xbap). Insert the .xbap extension and things work alright again.