#1,111 – Referencing Content Files from XAML

You can choose whether to embed an image resource in your application’s executable file or to have the file copied to the output directory.

Whether the image resource is embedded in the executable or copied to the output directory, you can reference the image from XAML elements in the same way, by just using the name of the image (assuming that the image is located in the root of the solution).

Below, the “Chico” image has its Build Action set to Resource (embed in executable).  The “Groucho” image has its Build Action set to Content (read from output directory).

1111-001   1111-002

In XAML, we refer to the images in the same way.

    <StackPanel Orientation="Horizontal">
        <Image Source="Groucho.jpg" Height="100"
               Margin="10"/>
        <Image Source="Chico.jpg" Height="100"
               Margin="10"/>
    </StackPanel>

When we run the application, both images are loaded successfully.

1111-003

Advertisement

#1,110 – Using a Resource as a Content File

When your application needs to use a resource (e.g. an image), it can embed the resource in the executable for the application.  You can then access the resource at run time using a Uri like the one shown below.

BitmapImage bmi = new BitmapImage(new Uri("pack://application:,,,/Ted.jpg"));

You can also include an image in your project and then cause the image to be placed in an output directory along with the executable, but not embedded within it.  You do this by setting its Build Action to Content and by setting the Copy to Output Directory property.

1110-001

In this case, after building the project, the .jpg file is copied to the output directory.

1110-002

At run time, you can use exactly the same Uri to access the file, although it is external to the application, rather than embedded.

#1,108 – Use Reflector to Get List of Resources

You can use the third party .NET Reflector tool to get more information on the contents of a .NET (e.g. WPF) assembly.  .NET Reflector is available from Red Gate Software.  Included in the list of information displayed in Reflector is a full list of all resources embedded in the assembly.

To start with, you open the assembly within Reflector.  You do this by browsing to the .exe file containing the assembly.

1108-001

 

Once you open the assembly, you can look at the contents, including any resources embedded within the assembly.  In the example below, we find the image ted.jpg in the images sub-folder.

1108-002

 

 

 

#1,107 – Accessing an Embedded Resource Using a Uri

You can embed images into your WPF application as resources and then access them from code at run-time.

To embed an image as a resource, add it to your project and set its Build Action to Resource.

1107-001

You can now access this image at run-time using a Uri.  The URI for a simple resource just includes the path to the image.

In the example below, we use a URI to locate an image in the Images folder.

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                BitmapImage bmi = new BitmapImage(new Uri("pack://application:,,,/Images/Ted.jpg"));

                MessageBox.Show(string.Format("Image is {0}x{1} pixels", bmi.Width, bmi.Height));
            }
            catch (Exception xx)
            {
                MessageBox.Show(xx.ToString());
            }
        }

The pack://application portion of the Uri indicates that the resource is compiled into the current assembly.  The portion of the Uri after the third comma describes the path to the image.

1107-002

#552 – Setting a Property to Use an Existing Resource

You can use Blend to create resources for objects (e.g. brushes) that you want to use in several places in your user interface.  Once you’ve defined a resource, you can use it as a value for a property on a control.

Let’s say that you’ve defined several resources within the resource dictionary for a Window.  Below, we’ve defined a couple linear gradient brushes and a couple solid color brushes.

Now let’s say that you’re trying to pick a brush to use for the Background property of a Button.  You can select the Button and then find its Background property on the properties panel.

Now set the Background to use an existing resource by clicking on the small square at the right side of the property and selecting a resource from the Local Resource submenu.  Under this menu, you’ll see all of your resources listed.

#551 – Resources Are Listed under the Resources Tab in Blend

When you convert an object to a resource using Blend, the definition of the object is moved from the control where it was defined into a resource dictionary and given a unique name.

In the XAML fragment below, the resource dictionary defined for the Window contains a single entry with the key “BrushBlueFade”.  The Label control then uses this brush by name for its Background property.

In Blend, you can see all of the resources that you’ve defined by clicking on the Resources tab.  Below, we can see the “BrushBlueFade” resource under the Window object, as well as a preview of the resource.

You can modify a resource directly from this panel by left-clicking on it.  In this case, we get the normal palette for editing a gradient brush.

You can also view the XAML for the resource by right-clicking and selecting View XAML.

#377 – Reuse Tooltips by Defining Them as Resources

Because tooltips are instances of the Tooltip control, you can create tooltip instances in a resource dictionary and then reuse them for multiple controls.

Below is an example of a tooltip that uses data binding to display the full text of a TextBox control.

    <Window.Resources>
        <!-- Standard tooltip for TextBox controls, displays Text property of parent control in a TextBlock -->
        <ToolTip x:Key="textBlockTooltip" DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
            <StackPanel>
                <Label FontWeight="Bold" Content="Full Text"/>
                <TextBlock Text="{Binding Text}" TextWrapping="Wrap" Width="200"/>
            </StackPanel>
        </ToolTip>
    </Window.Resources>

We can then use this tooltip on any TextBox control.

        <TextBox Text="Now is the winter of our discontent etc"
            Width="100" Margin="10" ToolTip="{StaticResource textBlockTooltip}"/>
        <TextBox Text="All the world's a stage etc"
            Width="100" Margin="10" ToolTip="{StaticResource textBlockTooltip}"/>


#148 – Property Values Set Using Expressions Overwrite the Base Value

In the list of all possible sources for a dependency property value, we explain that a property’s base value can in turn be overwritten by the result of an expression.  If the property’s value is set using an expression, the value of the expression takes precedence over the property’s base value.

In WPF, if the value of a dependency property is set using an expression, the expression can be one of two types:

  • Data binding – set the value of the property by binding it to another property
  • Resources – set the value of the property to a resource, loaded from a resource dictionary

 

#53 – Accessing Application-Scoped Resources from Code

You can access application-scoped resources from code by using the Application.Resources property.  The property points to a ResourceDictionary that contains a collection of DictionaryEntry objects.

For resources defined in XAML, the key of each entry is a string and the value is an object of the associated resource type.

For example, for the SolidColorBrush resource shown below:

 <Application.Resources>
     <SolidColorBrush x:Key="greenBrush"  Color="Green"/>
 </Application.Resources>

The dictionary entry’s Key is the string “greenBrush” and the Value is a SolidColorBrush object with the Color property set to green.

 SolidColorBrush br = (SolidColorBrush)Application.Current.Resources["greenBrush"];

#52 – Defining and Using Application-Scoped Resources

WPF resources can be associated with the main Application object, if you want them available throughout the application.

You can define application-scoped resources in the main Application XAML file (App.xaml).  In the example below, we define a green brush.

<Application x:Class="WpfApplication.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml" Startup="Application_Startup" >
    <Application.Resources>
        <SolidColorBrush x:Key="greenBrush"  Color="Green"/>
    </Application.Resources>
</Application>


To use this resource, you use a XAML extension to reference a static resource.  In the example below, we set the background color of a button in our main window to the green brush that we defined above.

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="224" Width="334">
    <Grid>
        <Button Content="Button" Background="{StaticResource greenBrush}"
                Height="23" HorizontalAlignment="Left" Margin="60,57,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>