Can we have one .exe calling a .dll with XAML and Prism (for MVVM)? - prism

My question is this: How can I call a library project (DLL) that contains all my XAML (Views) and ViewModel classes from another project that is meant to only run as an "EXE"? (I want to use Prism 7 for MVVM purposes).
My intent is to have one project whose only purpose is to create an .EXE. This EXE will load the assembly where the actual WPF views and the viewmodels reside.
Ideally, I'd like to have App.xaml in the EXE project... But I want to have my Bootstrapper in the Assembly project... Is this possible with Prism 7?
I want to have an App.xaml in "Company.Product.Application" project (which produces an EXE):
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Company.Product.Application"
xmlns:Presentation="clr-namespace:Company.Product.Presentation;assembly=Product.Presentation"
DispatcherUnhandledException="Application_DispatcherUnhandledException"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources>
<ResourceDictionary>
<Presentation:AppBootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
</Application.Resources>
Then from my Bootstrapper, I want to load my IoC and create my views and viewmodels.
I have been able to accomplish this with Caliburn.Micro... The idea here is that "Company.Product.Presentation" DLL can be tested out without having to create an EXE in itself. I could add the reference to "Presentation" in my test project (NUnit) and test it independently. The EXE is just a project that calls on "Company.Product.Presentation" DLL to actually generate Graphical User Interface goodness.
I appreciate any insight you may have in regards to this question. Thanks!

But I want to have my Bootstrapper in the Assembly project... Is this possible with Prism 7?
Sure, just reference the dll with the bootstrapper from the exe and put something like this in App.xaml.cs:
protected override void Onstartup(StartupEventArgs e)
{
base.OnStartup(e);
var bootstrapper = new Company.Product.Presentation.Bootstrapper();
bootstrapper.Run();
}

Related

Why do I need to change assembly names in my Xamarin.Forms app?

I am wrote this XAML code in an Xamarin.Forms app (multiplatform):
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyNameSpace;assembly=MyAssemblyName"
Padding="0,20,0,0">
<TabbedPage.Children>
<local:Page1 />
<local:Page2 />
...
MyNameSpace is the namespace I choose when creating the project, and MyAssemblyName is the project name.
Page1 and Page2 are others XAML/cs pages.
This does not work. I had errors on Xamarin preview and at execution. Those errors said my assembly name is not found or something like that.
I have checked options in iOS and Android sub projects. Those options where auto generated at creation.
I see that assembly names are: MyAssemblyName.iOS and MyAssemblyName.Droid
If I rename both to MyAssemblyName, my project works.
My questions are:
Is it a good thing to have the same assembly name for iOS and Android project?
Why this tags did not work with default assembly names?
You are probably in a "Shared Project". If this is the case, each platform you have in your solution has an assembly, but the Shared Project (the one you write most of the code) doesn't.
The solution for this error is to simply remove the assembly=MyAssemblyName from the xmlns:local string. It should be xmlns:local="clr-namespace:MyNameSpace;"

Multi-targeted WP7.1/WP8 app with Windows Phone Toolkit (Panorama / LongListSelector)

Was wondering if someone had a good idea of how to handle this.
In WP7.1, we can utilize the excellent Windows Phone Toolkit to include some useful controls such as LongListSelector and Panorama. These are part of the Microsoft.Phone.Controls.Toolkit assembly.
In WP8, we do not need the toolkit for those two controls because they're part of the official Microsoft.Phone.Controls assembly.
I have multi-targeted my app so that I have two phone projects, WP71 and WP80, where I link files in WP80 to files in WP71.
This works great until I try to use the Panorama or LongListSelector control in a XAML page. In the WP80 project, if I reference the WP80 DLL of the phone toolkit, it does not include the two aforementioned controls because, surprise, they're already present.
The issue is, WP71 needs the namespace declaration at the top of the XAML and the namespace is different for both projects.
WP71:
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
<toolkit:Panorama />
WP80:
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
<phone:Panorama />
I cannot build the projects because each project thinks the namespace is incorrect if I just use one because they need to point to different assemblies.
I don't think I can use compile constants in my XAML, otherwise that would be a fix.
My workaround was originally to just reference the older WP71 DLL in my WP80 project. But other 3rd party libraries bind against the official 8.0 SDK DLL (Caliburn, in my case) so it causes problems.
How can I solve this pickle? The only idea off the top of my head was to resort to code-behind to create the instance of the control :( Is there a better way?
Don't use a link, create a separate view for each.
Another solution might be to create a PanoramaEx control in each of the relative projects and inherit from Panorama. Then the view would reference the PanoramaEx control and you could still use a link to a single view. That's if both UI projects have the same namespace.
Edit: isn't panorama for WP7 in the namespace:
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
I do use my initial solution for ProgressBar and PerformanceProgressBar, I have a ProgressBarEx in each UI project, the WP7 one inherits from ProgressBar and the WP8 one inherits from PerformanceProgressBar and then in the views I reference ProgressBarEx.
Might not be the most elegant solution, but you can try to use a T4 file (.tt file) to generate both targets.
<## template language="C#" hostspecific="true"#>
<## output extension=".xaml"#>
<## assembly name="EnvDTE" #>
<phone:PhoneApplicationPage
x:Class="PhoneAppDemo.Pages.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
<# IServiceProvider serviceProvider = (IServiceProvider)Host;
EnvDTE.DTE dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));
var configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name;
if (configName == "WP7") { #>
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
<# }else{ #>
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
<# } #>
>
<# include file="Page.xaml" #>
</phone:PhoneApplicationPage>
In this example, the inner content of the Page is in "Page.xaml". We just encapsulate it in <phone:PhoneApplicationPage> at processor time, based on the target name (usually Debug and Release, but in this example we assumed there was a target WP7).
For other stuff related to a multi-targeted silverlight app, you can always read Maintaining a WP7 and WP8 version of a same Silverlight application.

adding visual studio XAML Intellisense to non-wpf classes

I have "DOM like" data structure in c# (parent, childNodes, properties, enums...) and I want to use xml\xaml file to some of the initializing. I already wrote a tool that transform my xaml to c# and inject them in the right place.
I want the exact Intellisense behavior of WPF except that my classes doesn't inherits from WPF base classes and my project in not wpf application on library and doesn't reference wpf assemblies. i also don't want to use xsd schema because classes are added and edited very frequently.
I'm using visual studio 2010
Is it possible?
Create a xaml (start by creating a resource dictionary and delete the content).
Add your own assembly as the default namespace and start using your types. I have created a test for sample data recently, here's how it looks like:
<MainViewModel xmlns="clr-namespace:MvvmTest.ViewModels.DesignTime"
Name="The design time main view model">
<MainViewModel.SubViewModels>
<FirstSubViewModel Name="The design time first sub-view model" />
<SecondSubViewModel Name="The design time second sub-view model" />
</MainViewModel.SubViewModels>
</MainViewModel>
You can load the file using the XamlReader class. As a bonus compared to xml, the file will be compiled and run time loading will be much faster.

The name "DictionaryEntry" does not exist in the namespace "using:System.Collections"

I am using the Consumer Preview of Windows 8 to create a Metro app. Whenever I add a new IValueConverter to a XAML page I receive the following exceptions from within the StandardStyles.xaml file:
The name "DictionaryEntry" does not exist in the namespace "using:System.Collections"
The errors point to this section of the StandardStyles.xaml file:
<ResourceDictionary.ThemeDictionaries>
<Collections:DictionaryEntry x:Key="Default">
<Collections:DictionaryEntry.Value>
<ResourceDictionary>
<x:String x:Key="BackButtonGlyph"></x:String>
<x:String x:Key="BackButtonSnappedGlyph"></x:String>
</ResourceDictionary>
</Collections:DictionaryEntry.Value>
</Collections:DictionaryEntry>
<Collections:DictionaryEntry x:Key="HighContrast">
<Collections:DictionaryEntry.Value>
<ResourceDictionary>
<x:String x:Key="BackButtonGlyph"></x:String>
<x:String x:Key="BackButtonSnappedGlyph"></x:String>
</ResourceDictionary>
</Collections:DictionaryEntry.Value>
</Collections:DictionaryEntry>
</ResourceDictionary.ThemeDictionaries>
This file was added automatically when I created a new Metro App project from the default Metro App project templates. The file compiled and ran fine before I added a IValueConverter to a page. The issue happens every time I add a IValueConverter, regardless of which project template I use, and regardless of if I add the IValueConverter using Expression Blend or Visual Studio.
This could just be a bug in the Consumer Preview release, but it seems like such a fundamental piece of work, that I figured it was worth asking here if anyone else has run into this issue and, if so, how were you able to solve or workaround it?

How to apply the Classic theme on my WPF4 form?

We are currently migrating our app from VB6 to Net. As the Net forms will be in the minority we want them to blend in as good as possible with the VB6 forms. I thought that forcibly applying the Classic theme would accomplish this. This should be easy but I can't find how to do it. The examples provided target the Aero theme or Net3 which seems to have differently named referenced assemblies.
There are two ways to accomplish this:
Reference the classic.xaml file that is embedded in the Framework:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Classic;component/themes/classic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
`
Download the extracted classic.xaml file from here
This file holds a reference to the PresentationUI.dll which does not seem to be part of Net 4 framework. There is just one quixotic Control using this reference, so when you remove the reference and the control you are set to go!
More info here

Resources