Tips: How to use SnapsToDevicePixels when creating a ControlTemplate

•October 11, 2008 • 1 Comment

After investigating the default control templates shipped by WPF, I conclude rules of thumb for creating the custom CoontrolTemplate. (The rules don’t necessarily apply on every single default control template of WPF, but I can say they work for most of them.)

1. use Border or Chrome as the outermost level of the custom control template, and set the Border/Chrome’s SnapsToDevicePixels to true

2. if the custom control template is supposed to contain ContentPresenter, ItemsPresenter or ScrollViewer, set the ContentPresenter/ItemsPresenter/ScrollViewer’s SnapsToDevicePixels to {TemplateBinding UIElement.SnapsToDevicePixels}. No matter how many levels stay between the outermost level and the ContentPresenter/ItemsPresenter/ScrollViewer, no need to set the SnapsToDevicePixels for them.

Exceptions:

1. No need to set SnapsToDevicePixels for custom control templates of Window, Frame and their subclasses. But it is also OK to set it.

2. ContentControl’s control template does not have a top level container working as layout, but only has a ContentPresenter. Anyway you do not need to customize a control template for ContentControl either.

3. Rules above don’t by default apply on ScrollViewer, ReaderPageViewer, FlowDocumentPageViewer, FlowDocumentScrollViewer, FlowDocumentReader, DocumentViewer and their subclasses. It is better to check their default control templates before starting to make the custom ones.

P.S.:

What is SnapsToDevicePixels about?

How to: Find Control/DataTemplate-Generated Elements

•October 8, 2008 • 1 Comment

http://msdn.microsoft.com/en-us/library/bb613586.aspx

http://msdn.microsoft.com/en-us/library/bb613579.aspx

To find an element within the template after the template has been applied, you can call the FindName method of the Template.

// Finding the grid that is generated by the ControlTemplate of the Button
Grid gridInTemplate = (Grid)myButton1.Template.FindName("grid", myButton1);

PS: for datatemplate, it is a bit tricky, because the datatemplate is actually applied on the contentpresenter. Therefore, you need first find the contentpresenter of the content control and call FindName on the ContentTemplate of the controlpresenter. Reference the second link above.

Attached Properties spreadsheet

•November 15, 2007 • Leave a Comment

Dr.WPF contributed a spreadsheet he compiled by himself. The spreadsheet listed all the current attached properties in WPF framework. It is definitely a good reference!

I uploaded the spreadsheet as well, for backup purpose. Because of the file extension limit, I have to change the extension to .doc. You can just change it back to .xls after you download it.

Download: attachedproperties.doc

A good tutorial about how to write and use attached property

More advanced attached property use: the Ramora pattern

Italia – Chris Botti

•October 21, 2007 • Leave a Comment

Lately I have been picky with music. I ran into some albums, nearly none of which I could really enjoy. Only one of them kept me hearing over and over again. To some extent, probably just because of its excellence, other albums unfortunately had to be covered by its shadow. It is always sadness to exist in the same time with the master piece.

Now, to all the fans of soft music, I strongly recommend this album, Italia, from Chris Botti. I always believe the beautiful music should not be described by words, because it can express itself by its melody. Therefore, I say no more. You just take a chance to enjoy.

01. Deborah’s Theme (from “Once Upon A Time In America”)
02. Italia featuring ANDREA BOCELLI
03. Venice
04. The Very Thought Of You featuring PAULA COLE
05. Gabriel s Oboe (from The Mission )
06. I’ve Grown Accustomed To Her Face featuring DEAN MARTIN
07. Caruso
08. The Way You Look Tonight
09. It Never Entered My Mind
10. Ave Maria
11. Estaté
12. Nessun Dorma

In this list, personally I like Italia, Venice, The Way You Look Tonight and Nessun Dorma most. Hope you will like them as well.

How to retrieve a FrameworkElement in a data template for ListboxItems

•October 17, 2007 • Leave a Comment

Update:

Object container = SomeItemsControlInstance.ItemContainerGenerator.ContainerFromItem(item);

The container is the top element, right under the ItemsPanel, for each of the items.

For example, ListBoxItem for ListBox, ContentPresenter for ItemsControl.

Just list some references for now. gonna complete it later.

http://msdn2.microsoft.com/en-us/library/ms753298.aspx

http://www.beacosta.com/blog/?p=7

VisualOperations class is replaced by VisualTreeHelper Class

IsSynchronizedWithCurrentItem

•October 12, 2007 • 2 Comments

“IsSynchronizedWithCurrentItem” helps the selector controls synchronize with current item, which confuses me with “selected item”. I really can not see the point of current item, since we have access to the selected item.

MS gives an example of the use of the attribute, saying “suppose that there are two ListBox controls with their ItemsSource property set to the same source. Set IsSynchronizedWithCurrentItem to true on both list boxes to ensure that the selected item in each ListBox is the same.” I tried it. It seemed not to work as it said. Anyway, I don’t quite care about it, since I do not use it at all.

Here what I say about it is the annoying result if you set this attribute of a list box to true. Then no matter if or not the SelectedItem is set to -1, the first item will be always selected, which pissed me off.

I do not like it, therefore I always turn it off.

Learning Adorner

•October 4, 2007 • Leave a Comment

A WPF Project Needs Structure

•September 30, 2007 • Leave a Comment

The great and mysterious Dr.WPF gave a very good guideline of a WPF project’s structure. Check here out!

Compile meida files into a separate assembly

•September 30, 2007 • Leave a Comment

1. Setup a WPF User Control Library project in VS2008, and remove the user control files.

2. Create a folder of “Resources”, underneath create folders of Images, Videos, Audios, and the like.

3. Stuff each subfolder with the corresponding media files. Make sure the Build Action of any of them is “Resource”.

4. Build the whole project, then you can the assembly containing the binary resources.

To access these binary resources,

1. Add the reference to the assembly into your project.

2. Reach the concrete resource by the URI of, for example, “/ResourceAssemblyName;component/Resources/Images/TheImage.png”. The URI of this formate can be consumed either in XAML or in procedural code.

Make a theme-changable application

•September 28, 2007 • 1 Comment

This is how I do to make the real application theme-changable

1. Set up an independent project of WPF User Control Libaray. Remove the default generated user control

2. Create a folder called Themes. Under this folder, add bunch of ResourceDictionaris.

3. Open up each of the ResourceDictionaris and edit the styles and whatever necessary.

4. Compile the project to dll, and Done!

To link the theme dll, you add the preference to the dll into your theme-consuming project. You can consume the themes by either merging them in Application.Resources or loading them dynamically.

To merge a theme, you put the following XAML code into the Resource section of App.xaml

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source=”/ThemesAssemblyName;component/Themes/ATheme.xaml” x:Name=”theme”/>
<ResourceDictionary Source=”OtherTheme.xaml”/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

To load a theme dynamically, such procedural code is required

ResourceDictionary theme = Application.LoadComponent(new Uri(“Themes/AnotherTheme/AnotherTheme.xaml”, UriKind.Relative)) as ResourceDictionary;
Collection<ResourceDictionary> mergedDicts = Application.Current.Resources.MergedDictionaries;
ResourceDictionary oldtheme = Application.Current.Resources.FindName(“theme”) as ResourceDictionary;
mergedDicts.Remove(oldtheme);
mergedDicts.Add(theme);

If you have the themes in the same assembly with your applicaiton, you should change the Uri to “Themes/ATheme.xaml”

Note: (Kinda off-topic, BUT!!!) when you define the control template for some control, no matter the control template is inline or wrapped by Style, the property of TargetType is required, otherwise, the Contentpresenter of that control will not work.

Note1: Use DynamicResource if you want the resource consumer can be dynamically rendered when a new theme is applied. Another thing is, use DynamicResource if the resource consumer in a data/control template, otherwise, the project will not be blendable.

Some sample links:

WPF: Expression Blend 2 and external resources (VS2008 version)
Create and apply custom themes
Creating a Skinned User Interface in WPF