По поводу вопроса "есть ли лучший путь". В дополнение к решению, которое вы упомянули, некоторые люди любят использовать состояние приложения для передачи параметров между объектами. Например:
PhoneApplicationService.Current.State["parameter"] = param;
var parameter = PhoneApplicationService.Current.State["parameter"];
Другой вариант - использовать общий класс. Со сложными объектами мне часто проще всего использовать статический открытый член в классе, к которому можно получить доступ из обоих проектов.
Обратите внимание, что если вы решите использовать навигацию по строке запроса, некоторые специальные символы в строке запроса могут вызвать проблемы. Если вы не можете контролировать содержимое данных, которые передаются между страницами, решение с общим классом, вероятно, лучше для вас. Например, в одном из наших приложений мы передаем имя веб-сайта в строке запроса. Бывают ситуации, когда эти имена могут содержать символ «&» (например, H & M), и если это так, строка запроса будет разбита.
При навигации, если сборка строк запроса становится громоздкой, вы можете проверить Caliburn.Micro и класс Uribuilder в нем. Это позволяет вам перемещаться с довольно хорошим (и беглым) синтаксисом:
navigation.UriFor<CandidateDetailsPageViewModel>()
.WithParam(x => x.CandidateId, candidate.Id)
.Navigate();
После навигации метод TryGetValue может быть весьма полезен при разборе параметров:
String parameter;
NavigationContext.QueryString.TryGetValue("Parameter", out parameter)
Дополнительные сведения о NavigationContext.QueryString доступны из MSDN.