Fix XamlObjectWriterException, Cannot create unknown type in F#, FsXaml, WPF app?

1.6k Views Asked by At

I am getting this error in a WPF app that is built with F#, FsXaml, and Elmish.WPF.

System.Xaml.XamlObjectWriterException:
Cannot create unknown type '{http://schemas.componentone.com/winfx/2006/xaml}C1ProgressIndicator'.
at System.Xaml.XamlObjectWriter.WriteStartObject(XamlType xamlType)
at FsXaml.InjectXaml.from(String file, Boolean loadFromResource, Object root)
  • A Views project contains XAML and includes a reference to C1.WPF.4.dll.
  • The XAML declares an instance of a control from C1.WPF.4.dll.
  • However, there is no F# code that uses any types from C1.WPF.4.dll.
  • Consequently, Views.dll does not contain a reference to C1.WPF.4.dll, as confirmed by IL Spy.
  • Consequently, when I build App.exe, C1.WPF.4.dll is not included in the output folder.
  • Consequently, I get a run-time error.

While I could include a reference to C1.WPF.4.dll in my App project, I would rather not.

Is there a better way to do this?

1

There are 1 best solutions below

2
On

To get this to work:

  1. In your XAML file, replace the XAML namespace with a CLR namespace. For example, instead of xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml" use something like xmlns:c1="clr-namespace:C1.WPF;assembly=C1.WPF.4".

This is required because when App.exe is running, it may not have loaded the controls library yet. It is in the controls library that an attribute creates the mapping from XAML namespace to CLR namespace. By explicitly stating the CLR namespace and assembly, the XamlReader can find the class to instantiate.

  1. Create a dummy instance in the Views code. The dummy instance is an instance of something from the controls library. This creates the dependency in Views.dll on the controls library.

    // force the compiler to add a reference to C1.WPF.4.dll
    let private forceC1DllReference = C1.WPF.Anchor.TopLeft
    
    type MainWindowView = XAML< "MainWindow.xaml" >
    

This second one feels like a hack. I wonder if there is a better way to say, "Please add a reference to this DLL even if I'm not using types from it."