Простого ответа на вопрос я так и не нашел. Была статья на StackOverflow (не смог повторно ее найти), где приводился такой подход:
1) Создать в class library словарь Themes/generic.xaml. Все ресурсы, описаные в нем расшариваются между компонентами сборки.
2) В этот словаре описать стиль окна/страницы.
3) Т.к. дизайнер VS2008 не "видит" ресурсов из generic.xaml, то нужно обращаться к ним не как к статическим ресурсам, а как к динамическим, т.е. при помощи расширения DynamicResource:
<Window x:Class="..."
...
Style={DynamicResource MyWindowStyle}>
...
</Window>
4) Убедиться, что сборка помечера атрибутом ThemeInfo.
Но данный подход у меня так и не сработал. В итоге поступил по-другому.
1) Создал Themes/generic.xaml
2) Описал в нем стиль окна, пометив ключем с указанием типа окна:
<Style x:Key="{x:Type MyWindow}"...
3) Добавил статический конструктор в окно, в котором указал в качестве ключа дефолтового стиля тип данного окна.
DefaultStyleKeyProperty.OverrideMetadata(
typeof(MyWindow),
new FrameworkPropertyMetadata(typeof(MyWindow)));
Если короче, то просто задал дефолтный вид окна. Это сработало. Не очень красиво, но с другой стороны, мы ведь вряд ли будем наследоваться от окна, определенного в xaml-размтке.
Уже позже набрел на статью, в которой описывается создание присоединенного свойства, которое бы расшаривало ресурсы между различными корневыми элементами в xaml.