View / ViewModel Locator for different Assemblies

Topics: Actions & Coroutines, Bootstrappers & IoC
Nov 3, 2011 at 3:56 PM

I've upgraded my Caliburn Micro application to the newewst Caliburn Micro 1.2 build and i encountered some issues. Neither my view or viewmodel could find eachother.

No i've managed to fix one side, which is the Viewlocator side, but i can't seem to to get the rest working. When calling an action from the view, the target cannot be found.

to clarify i will describe my project layout in a simple way

-CoolProject Solution

  -CoolProject (Main project exe) (reference to both viewer.dll and viewmodels.dll, and also loaded in assembly.Instance)

      - Bootstrapper.cs

  -Viewer (new project, so Viewer.dll) (where my views are located)

      - MainWindowView.Xaml (window)

  -ViewModels(new project, so ViewModels.dll) (where my viewmodels are located)

      - MainWindowViewModel.cs (viewModel)

 

in my bootstrapper i've added the following codes:

    
protected override IEnumerable SelectAssemblies()
        {
            var assemblies = new List { Assembly.GetEntryAssembly() };
            assemblies.Add(Assembly.LoadFrom("Viewer.dll"));
           // assemblies.Add(Assembly.LoadFrom("ViewerModels.dll"));
            var referencedAssemblies = assemblies[0].GetReferencedAssemblies();
            assemblies.AddRange(referencedAssemblies.Select(Assembly.Load));
            AssemblySource.Instance.AddRange(assemblies);

                       
            return base.SelectAssemblies();
        }
  
 protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
        {
           
            ViewLocator.NameTransformer.AddRule
                (
                @"(?<nsbefore>([A-Za-z_]\w*\.)*)(?<nsvm>ViewerModels\.)(?<nsafter>([A-Za-z_]\w*\.)*)(?<basename>[A-Za-z_]\w*)(?<suffix>ViewModel$)",
                @"${nsbefore}Viewer.${nsafter}${basename}View",
                @"([A-Za-z_]\w*\.)*ViewerModels\.([A-Za-z_]\w*\.)*[A-Za-z_]\w*ViewModel$"
                );

            ViewModelLocator.NameTransformer.AddRule
               (
                    @"(?<nsbefore>([A-Za-z_]\w*\.)*)(?<nsview>Viewer\.)(?<nsafter>([A-Za-z_]\w*\.)*)(?<basename>[A-Za-z_]\w*)(?<suffix>View$)",                    
                    @"${nsbefore}ViewerModels.${nsafter}${basename}ViewModel",                     
                    @"([A-Za-z_]\w*\.)*Viewer\.([A-Za-z_]\w*\.)*[A-Za-z_]\w*View$"
               );

            base.OnStartup(sender, e);
        }
 
 
Now the problem is that if i add an action to my window now in xaml (for example: cal:Message.Attach="Loaded = LoadBaseComponents()" )

 if i have in my MainWindowViewModel.cs the following:
        public void LoadBaseComponents()
        {
 
        }
the result is: Exception: Target not found.
Anyone got a clue where i'm going wrong?

Nov 4, 2011 at 8:51 AM
Edited Nov 4, 2011 at 8:52 AM

 

I've also added a screenshot while debugging with the source code of Caliburn. Apparantly, in the ActionMessage Class, in the Method Invoke, context.Target and context.View are both Null.

http://i41.tinypic.com/2mqunmg.png

Anyone got a clue where i'm going wrong ?

Nov 4, 2011 at 9:10 AM

Never Mind Solved it.

Apparantly, using those two NameTransformers, and adding the correct assemblies like i did was all i needed. The only thing that made it go wrong was my action call from Xaml.

this used to work (but doesn't anymore):

  cal:Message.Attach="Loaded = LoadBaseComponents()"

Now i have to write it this way and it works just fine:

cal:Message.Attach="[Event Loaded] = [Action LoadBaseComponents()]"