Stumbling Through

Join me as I stumble, bumble and fumble my way through some new developer technologies. We'll laugh, we'll cry, there may be a mouse tossed through a monitor, but in the end we will all hopefully learn something.
in

Stumbling Through: WPF (Style Part II)

 

We left off with a HotTrackListBox.xaml file, but never made a place to put it.  Since the purpose of this exercise is to create a library of style, a term I should trademark, our first order of business is to create a Visual Studio project to house this file.  Let's open up our Stumbling Through solution that was created in the previous posts.  If you never read the previous posts, well, that solution simply consists of one wpf project with one form containing a transparent multi-line list box.  We will be removing all style from that list box so that the entire Window1.xaml looks like this:

 

<Window x:Class="StumblingThroughWPFPartI.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="Window1" Height="300" Width="300">

    <Window.Resources>

        <ResourceDictionary>

            <ResourceDictionary.MergedDictionaries>

                <ResourceDictionary Source="/VisualFoundation;component/HotTrackListBox.xaml"/>

            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>

    </Window.Resources>

    <Window.Background>

        <ImageBrush ImageSource="Greenstone.bmp" />

    </Window.Background>

    <Grid>

        <ListBox Margin="79,68,79,94" Name="listBox1" FontSize="16">

            <ListBoxItem>

                <TextBlock Text="Me"/>

            </ListBoxItem>

            <ListBoxItem>

                <TextBlock Text="You"/>

            </ListBoxItem>

            <ListBoxItem>

                <TextBlock Text="Somebody else entirely"/>

            </ListBoxItem>

        </ListBox>

    </Grid>

</Window> 

Within this solution, we will add a new project called 'VisualFoundation', which will be our library of style.  We want this project to compile to a .dll, but also include all of the WPF references necessary to design our xaml.  We might end up putting some other user controls into this project, so lets choose the 'WPF User Controls' project template:

image

Delete the default UserControl1.xaml that the project template gives you, we won't be using that.  We will, however, be adding a new item to this project, a resource dictionary named 'HotTrackListBox.xaml':

image

Paste our hot track list box xaml code into this file, so that it looks like this (the details of this were discussed in the previous post):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

 

    <Style x:Key="HotTrackListBoxItemStyle" TargetType="{x:Type ListBoxItem}">

        <Style.Triggers>

            <Trigger Property="IsMouseOver" Value="True">

                <Setter Property="ListBoxItem.BitmapEffect">

                    <Setter.Value>

                        <OuterGlowBitmapEffect GlowColor="AliceBlue" GlowSize="4"/>

                    </Setter.Value>

                </Setter>

            </Trigger>

            <Trigger Property="IsSelected" Value="True">

                <Setter Property="ListBoxItem.BitmapEffect">

                    <Setter.Value>

                        <OuterGlowBitmapEffect GlowColor="AliceBlue" GlowSize="14"/>

                    </Setter.Value>

                </Setter>

            </Trigger>

        </Style.Triggers>

    </Style>

    <Style x:Key="HotTrackListBoxStyle" TargetType="{x:Type ListBox}" >

        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>

        <Setter Property="Background" Value="Transparent"/>

        <Setter Property="IsSynchronizedWithCurrentItem" Value="True"/>

        <Setter Property="ItemContainerStyle" Value="{StaticResource HotTrackListBoxItemStyle}"/>

        <Style.Resources>

            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />

            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />

        </Style.Resources>

    </Style>   

    <Style TargetType="{x:Type TextBlock}">

        <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}, Path=ViewportWidth}" />

        <Setter Property="TextWrapping" Value="Wrap"/>

    </Style>

</ResourceDictionary> 

Note that HotTrackListBoxItemStyle is now above HotTrackListBoxStyle... turns out I was wrong in my previous post about it being smart enough to find styles defined anywhere in the document.  it compiled the old way, but when I tried to execute it, it told me that it could not find HotTrackListBoxItemStyle.  Live and learn, I guess.

Now on to the heart of the matter here, how do we consume this style in our front-end project?  First off, as in any distributed solution, we need to reference the VisualFoundation project in our front end project.  Simply add the project reference:

image

Ok, so now what?  How do we tell our list box to use the Hot Track List Box style?  The list box itself definitely has a 'Style' property, but what to set it to?  Technically, the VisualFoundation project put that style into a resource dictionary, so lets just try and reference it directly:

<ListBox Margin="79,68,79,94" Name="listBox1" FontSize="16" Style="{StaticResource HotTrackListBoxStyle}">           

Hmmm... no go, I get an error saying that HotTrackListBoxStyle is not found.  So the project doesn't automatically 'know' the resources defined in a referenced project.  The idea here is that we'll need to create a local resource dictionary that includes the referenced dictionaries, the key to doing this lies in the 'merged dictionaries' tag.  This tag includes an interface for merging xaml files from other projects into a resource dictionary of the current project.  The syntax for creating a resource dictionary that includes our HotTrackListBoxStyle from VisualFoundation looks like this:

    <Window.Resources>

        <ResourceDictionary>

            <ResourceDictionary.MergedDictionaries>

                <ResourceDictionary Source="/VisualFoundation;component/HotTrackListBox.xaml"/>

            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>

    </Window.Resources>

So what the heck does this mean?  The first two lines define a Resource Dictionary for the current window.  Then we define the 'merged dictionaries', which are external resource dictionaries to include the dictionary being defined.  There could be multiple external resource dictionaries defined here.  The complicated tag here is the Resource Dictionary tag's 'Source' attribute.  The first portion specifies the name of the referenced assembly, while the second portion specifies the location in that assembly of the resource dictionary to include.  The 'components' portion is a keyword, followed by the path to the resource dictionary if it were under sub-folders.

Running our project, we get the desired results:

image

Note that 'Me' was clicked, giving it the brighter highlight, and 'Somebody else entirely' is being hovered over with the mouse, giving it the hot-track highlight.  We could manipulate the style to change the colors and magnitude of the highlight, but hey, its just a demo.

So what have we learned here?  I've barely scratched the surface on the power of styles, but at least I've proved that the concept of a 'library of style' is not only feasible, but really a preferred method of sharing common styles among multiple projects.  Where am I going next?  I'm not sure yet, there are several different paths I'd like to attempt:  I'd like to build on my library of style by adding default window and button styles.  I'd also like to open the can of worms that is databinding, and of course there is also LINQ which I have yet to discuss.  Can't forget about user controls either; as I would like to make a 'fading window' control that can fade in and fade out, while simultaneously fading music in and out.  We'll see what I stumble into next.

 

 

Leave a Comment

(required) 

(required) 

(optional)

(required)