tags:

views:

3199

answers:

6

I have a C# (2008/.NET 3.5) class library assembly that supports WPF (based on http://dotupdate.wordpress.com/2007/12/05/how-to-add-a-wpf-control-library-template-to-visual-c-express-2008/). I've created several windows, and am now attempting to create a common style set for them. However, as it's a class library (instead of a WPF app), I don't have an app.xaml (and its contained Application & corresponding Application.Resources) in which to store these styles for global access.

So: How can I create a top-level set of style definitions that'll be seen by all xaml files in the assembly, given that I do not have app.xaml (see above)? And/or is it possible to add a working app.xaml to a class library?

FYI, I did try creating a ResourceDictionary in a ResourceDictionary.xaml file, and include it in each window within a "Window.Resources" block. That turned out to solve the styling of Buttons, etc... but not for the enclosing Window. I can put 'Style="{StaticResource MyWindowStyle}"' in the Window's opening block, and it compiles and shows up in the VS Design window fine, but during actual runtime I get a parse exception (MyWindowStyle could not be found; I'm guessing Visual Studio sees the dictionary included after the line in question, but the CRL does things more sequentially and therefore hasn't loaded the ResourceDictionary yet).

A: 

if you load it in Window.Resource, the dictionary is only available for the children of that window. You need to have it available for the window and its children.

Try loading it in your app.xaml file. That should make it an application level resource, not a window-level resource.

Muad'Dib
Sorry, I guess I didn't make it clear enough originally (I just modified the desc. to fix) -- I don't have app.xaml as this is a class library.
WarpedBoard
"Sorry, I guess I didn't make it clear enough originally". This is stackoverflow, @WarpedBoard. Surely you don't expect people to actually read the question. ;)
mackenir
+2  A: 

This sounds like a job for theming.

  1. Add a /themes/generic.xaml ResourceDictionary to your project.
  2. Add the following to AssemblyInfo.cs: [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
  3. ?
  4. Profit!

Any resources you add to generic will be used by all controls. Also you can make profile specific themes (Luna, Aero etc.) by including a ResourceDictionary file with the correct theme name in the themes directory.

Heres a link to more info: Create and apply custom themes

Cameron MacFarland
this just helped a lot with a problem i've been having. thanks!i want the profit part.
moogs
A: 

Thanks for the ideas, but still no go... apparently a class library does NOT support the generic.xaml usage implicitly. I added generic.xaml to my class library project and set its Build Action to "Resource". It contains:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
    <Style TargetType="{x:Type Window}" x:Key="MyWindow">
        <Setter Property="Background" Value="Black"/>
    </Style>
</ResourceDictionary>

The window xaml that I want to have use the theme looks like this:

<Window x:Class="MyAssembly.ConfigureGenericButtons"
    x:ClassModifier="internal"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Style="{StaticResource MyWindow}"
    Title="ConfigureGenericButtons">
...Buttons, etc...
</Window>

Although the VS Design window doesn't show the window using the MyWindow style (ie black background), it compiles fine and starts up. However, when the app containing this class library makes a call that causes this window to display, I get a XamlParseException:

Cannot find resource named '{MyWindow}'.

I also tried leaving out the Style parameter, to see if the window would use the style by default (and I tried that both with the x:Key in generic.xaml included and without). No errors, but anything defined in the generic.xaml didn't show up either.

Am I doing something wrong here, or any other ideas on how one might allow for common custom styles to be used on a Window (ie, not have to define the styles in each Window's xaml) -- with the caveat that this is NOT an application?

WarpedBoard
A: 

If you dont have an app.xaml, you can still load it into the appplication-level resources, but you have to write code (not xaml) to do it, similar to this...

void LoadIt()
{
     ResourceDictionary MyResourceDictionary = new ResourceDictionary();
     MyResourceDictionary.Source = new Uri("MyResources.xaml", UriKind.Relative);
     App.Current.Resources.MergedDictionaries.Add(  MyResourceDictionary )
}

check out this site for an example: http://ascendedguard.com/2007/08/one-of-nice-features-about-wpf-is-how.html

Muad'Dib
+2  A: 

Try adding

Style={DynamicResource MyStyle}

You cannot use a StaticResource in this case.

Jab
Bingo! That's the missing Step 3... now to profit! Thanks for the answer...
WarpedBoard
No problem, glad to help. Mark the appropriate solution to help others seeking advice on this in the future.
Jab
A: 

To make a WPF application a class library and start it from a console application follow these steps :

1 - Change the output type from 'WindowsApplication' to 'ClassLibrary'. 2 - Change the build action for App.xaml from 'ApplicationDefinition' to 'Page', this will remove the 'Main' method from the autogenerated file 'App.g.i.cs' . 3 - Create a console application referencing the WPF class library and all the necessary WPF libraries(WindowsBase, PresentationFramework and PresentationCore) and set it as startup project . 4 - On the 'Main' method inside the console application, apply the STAThreadAttribute and add the following code :

App app = new App();
app.InitializeComponent();
app.Run();

If you set the Console project output type to 'WindowsApplication' the black console window wont show and it will be just like you started the application from the wpf project. You get the App.xaml as the resource root, but the resources defined in App.xaml wont be globally visible for the designer.

Thiado de Arruda