Monthly Archives: October 2015

WPF Resources

Resources in WPF terms, are simply mechanisms for storing data, whether it be strings, colours, brushes, styles etc.

We can store such resources locally, within the scope of a Window or control or we can store the resources globally within the Application resources.

Resources are stored as key value pairs within a Resources section or ResourceDictionary. We therefore need to define a x:Key for each item in the resources, for example

<Window.Resources>
   <system:Int32 x:Key="ButtonWidth">100</system:Int32>
</Window.Resources>

In the above XAML we’re storing an Int32 type in the resource of a Window class. The key is “ButtonWidth” and the value is “100”.

Now let’s look at some example of using the resources.

<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <FontWeight x:Key="Weight">Black</FontWeight>
    </Window.Resources>    
    <Grid>
        <Button Content="Hello World" FontWeight="{StaticResource Weight}" />
    </Grid>
</Window>

In the XAML above we are storing the resources within the scope of the Window. This means everything within the Window class will now have access to these resources but they’re not available outside of this Window.

We’ve created a FontWeight type resource with the key “Weight”. In the Button we use the resource to assign the value from the key “Weight” to the FontWeight of the Button. simply think of the key as a variable name.

Note: I’ll discuss the StaticResource at the end of this post

We can add resources to a top level UserControl (for example) just as we’ve done in the Window example, but we can also add resources to controls within a control or Window, for example, let’s take the Button from the above example but move the resource into the Button.Resources

<Button Content="Hello World">
   <Button.Resources>
      <FontWeight x:Key="Weight">Black</FontWeight>
   </Button.Resources>
   <Button.FontWeight>
      <Binding Source="{StaticResource Weight}"/> 
   </Button.FontWeight>
</Button>

Notice in the code above, we’ve used the Button.FontWeight element instead the FontWeight attribute of the Button (as per the original code). This is simply because when we add the resources in this way, these are now within the scope of the Button and unfortunately this means we cannot apply to the Button attributes themselves.

Application resources are defined in much the same way as for a Window resources but are available to all Windows/controls – in other words have global scope. We might declare our resource as follows

<Application x:Class="Test.App"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   StartupUri="MainWindow.xaml">
   <Application.Resources>
      <FontWeight x:Key="Weight">Black</FontWeight>
   </Application.Resources>
</Application>

Finally we can also create XAML files which are of type ResourceDictionary

<ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  
   <FontWeight x:Key="Weight">Black</FontWeight>
</ResourceDictionary>

Now to use this ResourceDictionary from our Window (or control) we need to writing the following

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MyResources.xaml"></ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources> 

This will merge the MyResources.xaml into the Windows ResourceDictionary and thus make the FontWeight resource available to the Window as if we’d declared it within the Window Resources. However by using the ResourceDictionary, not only can we create tidier code, removing possibly lots of resources from our views but also create libraries of resources that can be easily reused.

Resource Markup Extension

In the code above, we used the StaticResource markup extension. This is not the only option for binding to resources. We could also use the DynamicResource markup extension.

The use of StaticResource means that resource is resolved once at the point the XAML is loaded. Whereas DynamicResource allows us to in essence, late bind, to the resource. This means we can write XAML which might have a DynamicResource binding to a resource but the resource doesn’t need to exist until runtime. This option also allows the binding to update automatically if the resource changes. Hence if you want to bind to a resource which might change, then you can use a DynamicResource – this is obviously very useful when we’re dealing with the concept of themes.

And finally

In some cases we might want to use the resource in code. If we’re embedding the string for the key within the XAML, this means we’ll have to duplicate the string in code – duplication is not good. So instead we might prefer to store the string in source code to begin with and reference this in our XAML.

So let’s create a C# file named it whatever you like, I’m going to call mine’s Constants.cs

Now let’s just create the following static class

public static class Fonts
{
   public const string Weight = "Weight";
}

We can obviously use this “Weight” in our code, but in XAML we’re going to need to do the following change.

<!-- Original -->
<FontWeight x:Key="Weight">Black</FontWeight>

<!-- Becomes -->
<FontWeight x:Key="{x:Static local:Fonts.Weight}">Black</FontWeight>

How many methods in my classes ?

I won’t waste time on this post explaining why I had to do this, but I had to find the number of methods on a whole bunch of classes.

NDepend to the rescue. Using the CQLinq language I wrote

Application.Methods.Where(m => 
m.ParentType.Name == "ClassName1" ||
m.ParentType.Name == "ClassName2").
Count(m => !m.IsGeneratedByCompiler)

Now I’ll admit the list of classes was coded directly into the query, which is obviously no good for reusing the query, but this mean’t it was quick and easy to get the code up and running in no time at all – and thus get my answer.

How to reference an existing NuGet package from a new project

So the scenario is this…

I’ve created a solution, added my projects, added some NuGet packages and all’s good with the world. Then I need to add a new project and reference some NuGet packages which I’m already using.

What’s the best way to do this?

In the past I’d go to the “Manage NuGet Packages” on the references section of a project and add the package again. However here’s the problem with this solution – unless you specify a specific version (you’ll be doing this through the Package Manager Console), you may find a different version of a package installed into your solution, which has its obvious downsides.

What about referencing the assemblies you require directly, i.e. use Add Reference and browse for them? I don’t actually know (at this time) whether this causes problems for NuGet with updates etc. but it’s not a great way when a package requires multiple assemblies, which make up a package.

What we really want is a way to say, reuse this package (already downloads and installed in the solution file system) in my new project.

The solution is simple, but I never noticed it before (how embarrassing)

One of the projects I’m working on has NuGet packages hosted in-house and they change often (hey its continuous deployment, that’s cool). So when I create a new project, all I want to do is get NuGet to somehow reference my existing package(s) and have NuGet handle all the references etc.

Well it’s actually all there, built into NuGet/Visual Studio.

  • Select the solution in solution explorer
  • Right mouse click and select Manage NuGet Packages for solution…
  • Select Installed packages
  • Locate the package that’s already installed
  • Click the Manager button
  • Now simply locate your new project and tick the checkbox next
  • Click OK, sit back and relax