How to set a property to a DynamicResource reference in code

June 29, 2007

I recently needed to set a dependency property to a DynamicResource reference in code.  It’s easy enough to do in XAML, but a quick Google search turned up nothing which explained how to do it in the code-behind.  Hopefully this blog post will rectify that situation.

The magic method is FrameworkElement’s SetResourceReference.  Here is a quick demo:

XAML

DynamicResource reference in code (XAML)

C#

DynamicResource reference in code (C#)


How to use FindName with a ContentControl

June 28, 2007

Introduction

This blog post shows how to use the FindName method to gain access to a template-generated element within a ContentControl.  Along the way we will see how to make FrameworkElement’s FindResource method return a reference to a typed DataTemplate (i.e. a DataTemplate in a resource dictionary with no key, but only a DataType value).

Background

The FrameworkTemplate base class has a handy method on it called FindName.  You can call FindName on a template, passing it the name of an element in the template and the element on which the template was applied.  If the tree of elements generated by the template contains an element with the specified name, FindName returns you a reference to it.  If it can’t find the element with the name you specified, it returns null.

The problem

Suppose that we are using a ContentControl to display a data object, and that data object has a DataTemplate applied to it.  Also suppose that we need to programmatically interact with one of the elements in the data object’s expanded template.  It might seem like a simple task: just call FindName on the DataTemplate which is applied to the data object in the ContentControl, passing in the element name and the ContentControl.  However, if you try that approach you will quickly hit the following brick wall:

FindName with ContentControl (error)

As you can see above, if you pass the ContentControl into FindName an InvalidOperationException is thrown and the message is “This operation is valid only on elements that have this template applied.”  Suddenly this seemingly simple task just got tricky.

The solution

The problem here is that the ContentControl does not directly host the elements provided by the expanded DataTemplate.  It uses a ContentPresenter to do the dirty work.  If we want to use the FindName method we will have to pass that ContentPresenter as the second argument, instead of the ContentControl.  The DataTemplate is applied to the ContentPresenter, not the ContentControl.

Putting the solution to work

The demo project associated with this blog post has a very simple set of functional requirements.  When the user clicks on some text, it must rearrange itself, as seen below:

FindName with ContentControl (before and after)

In this demo app we call on the trusty Foo class to be our data object:

FindName with ContentControl (Foo class)

Here is the relevant XAML of the demo app’s Window:

FindName with ContentControl (XAML)

The DataTemplate declared in the Window’s resource dictionary is a “typed template,” meaning that it has no x:Key but only a DataType value.  Typed templates are automatically applied to instances of the data type with which they are associated.  In this case, all Foo objects in the Window will automatically be rendered by that DataTemplate.

The Window contains a ContentControl, whose Content is set to an instance of Foo.  When the user clicks on the ContentControl the OnContentControlMouseDown event handling method in the code-behind will be invoked.  That method is implemented like so:

FindName with ContentControl (code-behind)

The inline comments above should provide sufficient explanation for how the code works, so I won’t reiterate all that here.  If you have any questions feel free to drop a comment on this post.

Download the demo app here: FindName with ContentControl (demo project)  Be sure to change the file extension from .DOC to .ZIP and then decompress it.


Pros and cons of Visual Studio Orcas support for WPF

June 23, 2007

I installed the Visual Studio 2008 (‘Orcas’) Beta 1 recently.  The main reasons I decided to install Orcas were so that I can start learning about Acropolis and LINQ

I have been putting VS2008’s support for WPF to the test; to see what improvements have been made since the Orcas extensions for VS2005 were released back in August of 2006.  In case you have considered moving to VS2008 for your WPF development but aren’t sure if it is worth the 6 gig download and possible destabilization of your machine, perhaps this information will help you make a more informed decision.

O Intellisense, Intellisense, wherefore art thou Intellisense?

Before getting into the pros and cons of Orcas, let me first make an important statement for all you VS2005 + Orcas extension users out there.  The standard XML Editor in Visual Studio no longer has XAML Intellisense!  When I first opened up Orcas, whipped up a new WPF project, and opened Window1.xaml I quickly discovered that there was no Intellisense! 

The XAML editor in Orcas is not the standard good old XML editor.  It seems to be a new editor, and only this new XAML editor has Intellisense support.  The old hackery in the VS2005 Orcas extensions, which used XSDs to provide XAML Intellisense, is no longer being used.  The standard XML editor is now unaware of XAML.

If your default editor for XAML files is the XML Editor, you’ll need to change it.  In Solution Explorer right-click on a XAML file, select “Open With”, and then choose the “Visual Studio Windows Presentation Foundation Designer” option, click the “Set as Default” button, and then click OK.

Pros and Cons

PROS

  • The visual designer for WPF is more stable and has more features.
  • It has cleaner and more organized XAML Intellisense, particularly when you use property element syntax.
  • It has better XAML Intellisense support for attached properties (they appear as namespaces in the Intellisense window).
  • There is a useful feature for mapping CLR namespaces into XAML, shows a list of CLR namespaces and which assemblies those namespaces are in.  You just select the namespace/assembly you want to map and it writes out the rest for you.  This even includes your “local” namespace too!
  • Once a non-WPF namespace has been mapped into your XAML, the Intellisense will list types in that namespace, such as String, Int32, etc.
  • Non-WPF types, such as your own classes, now have Intellisense support.  For example, it will display the public properties on classes which you created.
  • The context menus in Solution Explorer make it quick and easy to add a WPF Window, Page, UserControl, and ResourceDictionary.
  • After adding a named element in XAML, you do not have to compile the project for that element to be available as a field in the code-behind.  You only have to save the XAML file.
  • The Property Window and XAML editor cooperate nicely.  The Property Window displays the element selected in the editor, and changes made in either view appear in the other.

CONS

  • Orcas crashes and throws odd errors much more often than VS2005, which is expected of a beta release, but still is annoying when you are trying to get work done.
  • Auto-completion of an XML element close tag is missing.  In the VS2005 + Orcas extensions editor, after you typed the closing angle bracket of an element it would automatically write out the element’s close tag for you.  That feature is sorely missed.
  • Support for auto-formatting of XAML is gone (i.e. Ctrl + E + D no longer works).  That REALLY sucks.
  • The WPF visual designer does not remember its state between runs.  It always opens the visual designer on top, at the same size.  Since I almost never want to use the visual designer, it’s annoying that I have to hide it every time I open a XAML file.
  • The XAML editor does not auto-indent when you add a child element.  You have to hit Tab (or the Spacebar several times) to indent the child element appropriately.  This is just another time consuming task which I took for granted before.
  • XAML Intellisense does not give an informative comment about a property or event; it only shows the type and member name.
  • There is an inconsistent editing experience regarding auto-completed double quotes (“”).  If the property being set has a well-known set of values, like Background, then when you select a value it adds the quotes.  But for a property which requires you to type in the value, like Height, the quotes are not added.  This breaks my XAML editing flow and I find myself having to go back and add in double quotes around attribute values more often than I’d like to admit.
  • Giving an element a name in the Properties Window uses the Name property, instead of x:Name.  I prefer x:Name for the sake of consistency since you cannot always use Name, but can always use x:Name.  This should be configurable.
  • If you create a new class in your project and want to use it in XAML, you must close the XAML editor/designer and reopen it for the type to appear in Intellisense.

Wish List

  • The Visual Designer should NOT always open by default when I view a .xaml file!!!  It should remember my previous settings.
  • I’d love to have Intellisense support in markup extensions, such as showing the properties of a Binding, and displaying available resource keys when using StaticResource or DynamicResource.
  • I would also like it if there was Intellisense support for things like Setter.Property, Setter.Value, Trigger.Property, Trigger.Value, etc.  That would make the whole styling system in WPF much more user-friendly.

Conclusion

The support for WPF in Visual Studio 2008 is headed in the right direction, but still has a ways to go before hitting the point where I would say that it is far superior to what the Orcas extensions for VS2005 provided.  In some ways I think that the XAML editing experience has been degraded, but that might just be due to the fact that I’m so accustomed to the “old way” of doing things.  Regardless, since Acropolis and LINQ can only be used in VS2008, I will be using VS2008 from now on.


A five-mile overview of WPF

June 22, 2007

All of my blog entries thus far have assumed that the reader is already fairly familiar with the Windows Presentation Foundation.  In this entry I’ll be taking a step back and covering the basics of WPF.  I hope that this entry proves beneficial to both WPF newcomers and people who need to give a brief overview of WPF to clients/co-workers/managers/etc.

Windows Presentation Foundation (hereafter referred to as WPF) is one of several subsystems comprising the .NET Framework 3.0. WPF is the subsystem responsible for providing modern user interfaces in the realm of desktop, mobile, and browser-based applications. The other subsystems, which are not discussed here, are Windows Communication Foundation, Windows Workflow Foundation, and Windows CardSpace.

The .NET Framework 3.0 is included in Microsoft Windows Vista. Vista UI development will be based on the WPF technology, but WPF is also capable of running on a machine with Windows XP with Service Pack 2, and Windows Server 2003.

Let us take a moment to briefly review the historical context in which WPF exists. The HWND windowing technology has been used by all versions of Microsoft Windows since the first incarnation of the operating system, which was released in 1985. There have been enhancements made to the HWND technology, but it is still the same old system as it always was. WPF replaces the HWND windowing system entirely – from the ground up. WPF is much more than just a set of high-level managed classes, it consists of the following layers:

Media Integration Layer – Abstracts the underlying platform and performs as much graphics processing on a computer’s graphics card as possible, thus freeing the CPU for other processing tasks. It is a complete replacement for Win32 rendering. It performs the task of drawing pixels to the screen.  This layer was written in unmanaged code because raw performance is crucial at this level.

Visual Layer – A set of low-level rendering primitives which provide fine-grained control over the rendering process (in managed code).

Framework Layer – A rich set of high-level managed classes used to build applications on top of the underlying WPF infrastructure. These are the classes that line-of-business application developers will use most often.

For an excellent overview of the layers and how to decide which one(s) to program against, read Pablo Fernicola’s blog entry WPF- Pick Your API Abstraction.

WPF offers the application developer an entirely new palate with which he/she can create appealing and distinctive user interfaces. The following list contains some of the major features (this list is by no means comprehensive):

XAML – eXtensible Application Markup Language is an XML-based language which can be used to declare .NET objects, or, more specifically in the case of WPF, the layout and settings of an application’s user interface. Using XAML to define an application’s UI has several benefits, most notably, it allows graphic designers to work on an application’s visual style without requiring him/her to deal directly with code.

Vector Graphics – The WPF rendering technology is vector-based. Vector-based rendering allows for high-fidelity scaling of complex drawings and text, including the primitive shapes (lines, curves, etc). Another benefit of using vector graphics is it works well with high-resolution displays; something which is becoming a problem for the antiquated HWND technology as the resolution of display units improves.

Documents – WPF has entire namespaces devoted to documents. It provides ample support for different layouts, annotations, packaging, and security. There are several controls that can be used to display high-fidelity documents.  There is also comprehensive support for the XML Paper Specification (XPS), which is a popular means of describing paginated documents via XML markup.

Styles – Styles in WPF are somewhat analogous to CSS classes in Web programming. They allow the developer to create an application-wide visual theme, or a skin for certain controls/pages/windows. There are even designer applications, such as the Microsoft Expression designers, that can be used to facilitate this process.  Styles are a fundamental tool in WPF programming for creating appealing and consistent user interfaces.

Animation – Animating portions of a user interface allows for smooth transitions between logically distinct states, which can make your application more intuitive to the user. They can also be just plain fun. Creating complex animations in WPF is a relatively painless process.

Rich Media Support – One of the major improvements seen in WPF is the rich support for video, audio, and images. WPF exposes this in-depth functionality via managed classes that can easily be incorporated into your applications.  For example, showing a video clip in your user interface is as simple as declaring a MediaElement and specifying the source of the video, all of which can be done in XAML (there’s no need to write a single line of code).

3D – WPF has built-in support for 3D programming. There are classes in the framework which allow the developer to program with 3D meshes, light sources, surface materials, cameras, etc.

Ink-Enabled –WPF has ample support for ink/stylus integration built into it. The core user interface classes include ink/stylus functionality as part of their fundamental design, enabling the platform to be used seamlessly on Tablet PCs.

For those experienced with Win32 programming, or any of the technologies which encapsulate Win32 (such as MFC or Windows Forms), one can immediately recognize that all of the things listed above are either difficult or practically impossible to achieve with HWND-based technology.  WPF literally allows the Windows developer to create an entirely new breed of user interface.

One of the most exciting aspects of WPF is that all of the various feature spaces (as listed above) can be used with each other seamlessly.  For example, you can create a 3D object which is animated to move around the screen, while displaying a video that is “wrapped” around the shape.  If you are interested in seeing some top-notch demonstrations of WPF in action, be sure to check out this blog post.  It provides links to many notable applications which use WPF to create a modern user interface.

It’s a brave new world!


Overview of attached properties in WPF

June 22, 2007

My previous blog entry focused on dependency properties.  In that entry I briefly mentioned a type of dependency property called the attached property.  This entry explores attached properties in detail.

Attached properties are a special form of dependency property.  They exist so that a child element can store a value associated with a property defined on an ancestor element.  This is commonly used in the interaction between elements and the WPF layout infrastructure, such as an element informing a DockPanel that it should be docked to a particular side of the panel.  The value which an element has for an attached property is stored by that element, not by the element which exposes the attached property.  This is in stark contrast with the extender provider model used in WinForms, where the “extended” property only appeared to exist on other controls, but the backing store actually existed on the object which defined the extended property.

Using attached properties in XAML is very intuitive.  The following example shows how the DockPanel.Dock attached property can be set on any element (in this case, a Button) within a DockPanel.

<DockPanel>
    <Button x:Name=”btn” DockPanel.Dock=”Left”/>
</DockPanel>

The equivalent C# code for setting the attached Dock property on a Button is:

DockPanel.SetDock( btn, Dock.Left );

Both of the code snippets above express the same thing; the Button should be docked to the left side of the DockPanel in which it exists.  What is not expressed in the code is that if the Button is not contained within a DockPanel then the setting has no effect.  This is consistent with the semantics of attached properties in general: if the property setting has no meaning in a given context, it is ignored.

Attached properties differ from normal dependency properties in several ways.  The most noticeable is that they are not wrapped in CLR properties (i.e. standard .NET properties).  There is no class in which it would make sense to declare the CLR property for an attached property.  If the CLR property were on the class which exposes the attached property, there would be no way to associate different values for different elements.  On the other hand, the CLR property could not be defined on all possible classes which might use the attached property, simply for practical reasons.

The solution to the problem of how attached properties should be declared lies in a method naming convention.  An attached property named Foo exposed by the Bar class would be exposed by two static methods in the Bar class definition, one called SetFoo and the other called GetFoo.  The setter must have two parameters: the first is the element for which the value is being set (usually of type UIElement) and the second is the actual value of the attached property for that element.  The getter simply takes the element for which the value is to be retrieved and returns the associated value.  The WPF property system looks for methods which follow that naming convention when dealing with attached properties.

Other differences between attached properties and normal dependency properties include the methods used to register them with the property system (DependencyProperty.RegisterAttached and .RegisterAttachedReadOnly instead of .Register and .RegisterReadOnly), and where the property values are stored (on the element which consumes the property instead of the element which declares the property).

To learn more about attached properties, read the Attached Properties Overview page in the Windows SDK.


Overview of dependency properties in WPF

June 22, 2007

In my previous blog entry we examined the routed event system used by WPF.  Similar to how routed events augment the standard .NET event-driven programming model, dependency properties take standard .NET properties to another level.  In this entry we will discuss what dependency properties are and what advantages they bring to WPF development.

 

WPF leverages a property system which allows for much more sophisticated and intelligent usage of properties than was possible before.  In addition to using regular CLR properties, the Windows Presentation Foundation also uses dependency properties.  Dependency properties are used when the resolution of a property’s value is based on other properties or runtime settings (such as operating system settings). 

 

Here are some important features of dependency properties: 

  • Value resolution – DPs are used to form a system which can determine the actual property value based on various runtime information.  The resolution process has an order of precedence it assigns to various environmental contexts in which the property might exist.  For example, if the DP is being modified by an animation then the value supplied by the animation is the resolved value, but if it is not animated, then the value is derived from elsewhere.

  • Self-contained validation – DPs can have custom callback methods execute when the property value has changed.  These callbacks can validate the new value or coerce the new property value into something acceptable, according to the semantics of the property.

  • Default values – DPs provide a consistent mechanism for associating a default value with a property.  A DP’s default value has the lowest precedence in the value resolution process, meaning that if there is no other way to determine the property value, then the default value will be used.

  • Property metadata – The property system knows how a DP should behave based on metadata supplied at the time the property is registered with the system.  Subclasses can tweak a DP by overriding the property’s metadata, instead of completely re-implementing the property itself.  It is interesting to note that this metadata is not stored in attributes, partly because the performance impact associated with using reflection to manipulate the metadata was unacceptable.

  • XAML friendly – Just like normal properties, DPs can be set in XAML.

  • Value inheritance – Any DP can be given the ability to inherit its value from the property setting on an ancestor element, in the logical tree.  This provides similar functionality to the ambient properties used in Windows Forms.  Value inheritance is useful in many situations, such as propogating a data source down the element tree, font settings, flow direction (right-to-left) settings, etc.

  • Attached properties – A form of dependency property which allows a child element to store a value associated with a property defined on an ancestor element. 

Dependency properties are used to support many features in WPF, and also many features can only be used in conjunction with dependency properties.  For example, the data binding system in WPF is rooted in the FrameworkElement.DataContext dependency property.  The value of that property is inherited by all descendant elements, meaning that all elements in a logical tree can implicitly share the same data source.  On the other hand, only dependency properties on a framework element can be bound to the data source.  WPF data binding utilizes and requires dependency properties.  To learn more about data binding in WPF, read this article.

 

Using dependency properties is typically very straightforward because it is conventional for them to be wrapped by a normal CLR property.  It is also possible to get and set the value of a DP via the DependencyObject.GetValue and DependencyObject.SetValue instance methods, respectively, but that is rarely necessary in most development scenarios.

 

It is also worth noting that a dependency property can only be created on a class which derives, directly or indirectly, from the System.Windows.DependencyObject class.  That class is very high up in the WPF class hierarchy, which allows the majority of classes in WPF to leverage dependency properties.

 

The following resources can be used to learn more about dependency properties:

 

Demystifying dependency properties - A blog post which examines how the value of a dependency property is determined.

 

Further demystification of dependency properties - An example-based continuation of the post listed above.

 

Dependency Properties Overview - Microsoft’s explanation of dependency properties.

 

Overview of attached properties in WPF – A blog post which examines a special type of dependency property known as an “attached property.”

 

Attached Properties Overview - Microsoft’s explanation of attached properties.


Overview of routed events in WPF

June 22, 2007

WPF introduces an augmentation to the standard .NET event-driven programming model.  A new type of event, called the routed event, allows for much greater flexibility in event-driven programming scenarios.  Subscribing to a routed event can be achieved with the same syntax as a “normal” event (referred to as a CLR event), because it is typical that routed events are exposed via CLR events.

Before discussing routed events any further, it is important to mention the concept of the visual tree.  A WPF user interface is constructed in a layered approach, where one visual element can have zero or more child elements.  The hierarchy of visible layers in a user interface constitutes what is known as its visual tree. 

Routed events are a new infrastructure provided by WPF which allows events to tunnel down the visual tree to the target element, or bubble up to the root element.  When an event is raised, it “travels” up or down the visual tree invoking handlers for that event on any element subscribed to that event it encounters en route.  Note that this tree traversal does not cover the entire visual tree, only the ancestral element chain between the root element and the element which is the target of the event.

Routed event diagram

Figure 1 – Routed events in the visual tree (image borrowed from Routed Events Overview article in the SDK.)

It is common that one logical routed event is represented by two actual events, one tunneling and one bubbling.  The naming convention for tunneling events is PreviewXYZ, where XYZ is the name of the bubbling event.  For example, PreviewMouseLeftButtonDown and MouseLeftButtonDown are a pair of routed events used to notify elements in the visual tree that the user has depressed the left mouse button.  Not all routed events have a tunneling event, and some events do not tunnel or bubble at all.  Those are referred to as direct events, and they are essentially the same as standard CLR events.

The routed notification pattern has many benefits.  One very important benefit of routed events is that a high-level visual element in a UI need not explicitly hook the same event on all of its descendants, such as MouseMove.  Instead it can hook the event on itself, and when the mouse moves over one of its descendants, the high level element will be notified appropriately.

Another important advantage of routed events is that elements at all levels of the visual tree can execute code in response to events of their descendants, without expecting the descendant to notify them when the event fires.   An ancestor element which hooks a tunneling event can even prevent its descendants from ever receiving both the tunneling and bubbling events at all (although it is possible for an element to demand that it is notified of the event, regardless of it is handled or not).

For more information about routed events, including how to create custom routed events, read Routed Events Overview from the SDK.


Follow

Get every new post delivered to your Inbox.

Join 288 other followers