by Abhi·Comments Off on Advanced WPF Part 3 of 5: Styles in Windows Presentation Foundation
Styles give our applications and elements consistent look and feel. In this section we will see how style hooks up to the resource system and property system in WPF. We will also see how to specify triggers in styles and how to specify default and custom styles.
A style is a named group of settings that will define the elements will appear. As you can see in the image below the basic structure of style contains a list of setter elements which specify a target property and a value. A style provides a way to set properties of a type of element and in WPF these properties are Dependency properties.
All the elements in WPF have style property. Generally we use a resource reference in the elements style property however we can also set it inline. The main motive behind defining a style is that the same style will apply to multiple elements and will give consistent look and feel to the application. We can define style at the
We provide the x:key attribute to the style so that the elements can refer that resource.
WPF Applying Styles
We can also define the style as shown below by specifying the TargetType of the style and this style will automatically apply to all the elements that are of that type unless specified otherwise.
WPF Applying Styles
We can use this property of the styles to skin our applications by the use of resource dictionaries. We can put the styles defining target types in both the resource dictionaries and switch between then to change the theme of the application.
In WPF we can define new styles that are using other styles as the starting point. This can be done by using the BasedOn property of a style. We can change or add the needed properties. You should remember that we cannot apply multiple custom styles to an element so this BasedOn property helps us.
WPF Extending Styles
Styles vs. Local Properties
When we set a property using a style it works the same way as setting the property any other way.
But there is something that only style can do and not properties. In a style we can add properties that do not match the target type as shown below. In this case the WPF elements will apply the property that makes sense and will ignore the rest of the properties.
WPF Styles vs. Local Properties
The styles support same range of triggers as control templates. However the targets of the trigger in style are the target elements whereas in the ControlTemplate the targets are the named elements.
Animation Property Trigger
As we have seen in the graphics section that the only trigger we set on an element is the Event trigger. We cannot set a Property trigger on an element directly so we can use style for this. That style can be inline or resource style.
Animation Property Trigger
Animation Event Triggers
As we can see in the image below we can also put event triggers in the style.
Animation Event Triggers
Items Container Style
When we are working with ItemsControls like the ListBox or a TreeView we generally define the DataTemplates for the ListBoxItem or a TreeViewItem to make use of DataBinding. When are not proving these specified conatiners to the items then WPF is doing that for us. This means WPF wraps the contents of DataTemplate in a ListBoxItem for a ListBox and in a TreeViewItem for a TreeView. Now, if we apply properties to these will not work well while working with Data Binding. So what we need to do is define the style of type ItemContainerStyle.
Items Container Style
Items Container Style
Styles, Templates and Controls
Styles enable controls to be visible by default. As we have seen in the previous sections that the controls depend on templates for their appearance. Also the controls get their templates form the themes\generic.xaml or theme specific resource dictionary. These default styles set much more than a template. We should hard code as less as possible about a control in the template. The default styles sets properties like default background, font, etc. As you can see in the image below we have applied a local style to a button but we have just set the font size where does the button get the other properties form?
WPF Styles, Templates and Controls
So what’s happening is that the local style for the button is setting the font size for the button and default style sets all the other properties for this button. So both the styles are merged and used in the button.
Any questions comments or feedback is most welcome.
by Abhi·Comments Off on Advanced WPF Part 2 of 5: Printing in Windows Presentation Foundation
In this section we will see how we can add printing support in WPF applications. We will start off with printing and XPS and then move on to XPSDocumentWriter and then we will have a look on how to work with print options and customize print dialog.
XPS – XML Paper Specification
The API for printing is the same as the API for creating the XPS document. XPS has two important features.
It provides native print spool option which is useful for WPF printing. XPS is designed to WPF native graphics model efficiently. In theory XPS can go to the target device and rasterized there to provide maximum fidelity. Although in practice most printers don’t know how to render xps but this was the design while designing XPS.
XPS acts as the fixed layout document format i.e. like pdf version of the WPF.
We can generate a XPS document by printing something using the Microsoft XPS Document Writer virtual printer. This is available on machines that have .NET 3.0 installed. When we print something using this device it saves a document in XPS format on the disk.
XPS Document Writer
The default viewer for XPS is internet explorer. It’s a file that contains all the pages to be printed. If we zoom in we will see that the text is scaling properly.
The file convention is based on what the office files use. If we change the extension of the file from .xps to .zip and extract the contents of it then we will see that there is a documents folder.
WPF PRint Documents Folder
If we go inside it we will see that there is a pages folder which will contain a file corresponding to each page.
WPF Print Pages Folder
When we open these pages in visual studio we will see WPF elements in it so this is xaml with base as FixedPage. All the shapes are rendered by Path. The text that XPS uses is Glyphs which derives from shape and it helps us define how the text looks like by using shapes. Glyph is a much lower level way of handling text than a text block. You should know that XPS does not use all the elements of xaml but only a limited set as all the systems running xps might not be running .NET
XPS Page in XAML
The font is specified as a file in a relative URI in the resources dictionary. These have scrambled names. The resources folder also has all the bitmaps in use as well. There are generally the Bitmaps of the text for which the licensing is not available for distribution.
WPF XPS Fonts
The directory structure shown below is just for the user’s convenience.
WPF XPS Directory Structure
We should look at the .rels file to see the entry points into the package. It contains a series of relationships which are the links identified by the URI. The document that we have has 3 relationships.
The entry point called FixedDocumentSequence.fdseq. This contains the links to all the pages. These roots types are all reflecte din the API
Identifies the metadata i.e. thumbnail
WPF XPS .rels
The class used for creating the XPS document is the same as the class for printing in WPF. It is XpsDocumentWriter. The target for the writer (XPS file or Printer) depends on from where we got the writer handle in the first place.
If we get the writer from the PrintQueue then the writer will write to the printer.
If the writer from XpSDocumnet’s CreateXpsWriterWriter method then the output will go to xps file on disk.
Let’s see this in action. Add the following code to the click handler of a button.
Now when we run the application then we ask the PrintQueue to give us a XpsDocumentWriter and to get that we just pass a null printable area. After that we will get an option to choose the printer as we have not already done that.
We select the actual printer and click on print. The PrintDocumentImageableArea contains the dimensions of the paper we are printing on. The Media Size height and width tells us the size of the paper. As you might know that we cannot print all the way to the end of the paper as it might put ink to the printer edges. So we have a margin specified via OriginalHeight and OriginalWidth. The units are in DPI i.e. 1/96th of an inch.
Then we return back to the application and the code for creating a textblock is executed. This will be the visual tree that we will be printing. As you can see in the code we have assigned the top and left margin the same as to where the paper can print.
Next we need to create the layout. This would have been automatically if our visual tree was hosted inside a window but as there is no window we need to do it. So measure, arrange and update the layout.
Then we print the document.
If we use the Microsoft XPS Document Writer as the printer
Then we will have the OriginalHeight and OriginalWidth as 0 in the PrintDocumentImageableArea.
Now when we reach the write method we get to choose the save location of the xps document.
The XPS file looks something like this. As the virtual printer told us that there is no margin the text is next to the edge.
Printing Multiple Pages
We cannot call the Write method twice as it will throw an error. So we need to follow a different technique to print multiple pages. We need to use the SerializerWriteCollater to print multiple pages. We call the BeginBatchWrite to start the print spooling process and then we will call EndBatchWrite after the finishing the print job. We can use the code below to see multiple pages printing works.
WPF Printing Multiple Pages
The XPS document will contain 10 pages.
WPF Printing Multiple Pages
In the previous section we how we can print Visual Trees. The overloaded write method of the XpsDocumentWriter takes a DocumentPaginator as input. DocumentPaginator is an object that knows how to display content in pages. FlowDocument, FlowDocumentPageViewer, FixedDocument uses this IDocumentPaginatorSource.
WPF Document Paginator
Multi Page – XPS
We can get a detailed control over the print document by handling the XPS object itself. The write method has 3 overloads that accept
FixedPage – For printing a single page.
FixedDocument – For printing single document
FixedDocumentSequence. – For printing Multi document print job
WPF Multi Page XPS
Let’s see this in action. In the code below we can see that we have added a FixedDocument that contains Fixed Pages. The FixedPage has a children collection that will contain as many items as we like and we have positioned them like we position children in a canvas. Then we add the page to the FixedDocument. We need to provide the PageContent that will go in to the PageDocument sequence and this will contain the links to the actual child pages itself. So we build the Page content and then point that at the child FixedPage object itself. IAddChild is how we add children to elements.
WPF Multi Page XPS
And the output looks something like below.
WPF Multi Page XPS
All the methods offered by the XpsDocumentWriter are also available in the Async form like WriteAsync. These perform the printing process using the User Interface’s thread idle time. The progress change and Progress complted eventes are raised for tracking the progress of the print process. It also provides a CancelAsync method that cancels the printing. For all this to work we need to be running in WPF User Interface thread that’s running a message loop as this requires the idle time.
The PrintTicket class represents some of the common features like Collation, orientation, resolution, quality, etc. these are the printer properties that are available when will click on printer properties button in the print dialog. It is also extensible so that the printer specific settings can be attached to the PrintTicket.
PrintTickets can have different TicketScopes like document, print job or a page.
We can get the default print settings of the printer from the PrintQueue object of the printer. There are two properties:
UserPrintTicket – Contains user defaults
DefaultPrintTicket – Contains system wide defaults
As you might expect that all print cannot do everything so we can make use of PrintCapabilities class to get the Valid PrintTicket options for specific printer and the printer specific custom options.
In the previous section we saw that the PrintDialog was automatically popped by WPF when the printer selection was required. But we can do this using the code as well. And me will need to do it via code at places where we need to find out the capabilities of the printer, etc. And then can set or get various printing options.
Queues and Servers
The classes PrintDialog, PrintTicket and PrintQueue (It is specific to a printer) are part of System.Printing namespace introduced by .NET 3.0. We can use this API to configure remote print server or PrintQueue. It also provides configuration options, discovery and monitoring. PrintServer represents a particular class with printers attached and can provide PrintQueue for each of the connected printers.
Any questions, comments and feedback is most welcome.
In this section we will have a look at how we can reuse resources, templates, xamls, custom elements and custom controls.
The first way of making UI reusable is using the Resource System provided by WPF. But this approach cannot be used at all the places because it is not supported for UI elements. We can define UI elements in the resource but if we use it more than one place we will get an error as the resource system will refer to the same underline object. So this approach will be useful where we can reuse the objects itself. So this approach is perfect for Freezeable as the types which derive from freezable are shareable. For example if we have a logo which needs to be shown at multiple places then we can define it as a resource and reuse it.
*A freezable object has two states – frozen and unfrozen. When an object is frozen, it cannot be modified and it cannot even fires events but the unfrozen state, it works same as a normal object.
There is a trick which works in compiled xaml scenarios can be used to define reusable framework elements. We use the compiled XAML’s deferred loading to give each resource reference a new copy. As in compiled xaml the Resource Dictionaries are loaded on demand. This won’t work if this xaml is parsed at runtime.
Let’s see this in action. Add the following code to your window. The resource that we see here has x:Shared to false. When you are typing this xaml you will not find this appearing in intellisense . The reason is because Microsoft has hidden it and it might go away in the future versions. Using this False value will help us share the component because it specifies that the object should not be shared and each element using this should have its own copy. Normally what happens when we ask for a resource what WPF does is it creates an instance of it and keeps it in handy and when some other objects asks for it WPF provides the same object reference. But as we have turned off the sharing of the resource WPF will not keep the reference of the object in memory and when another object asks for this reference then WPF creates a new one and give it to the object. This won’t work for parsing xaml.
WPF Resource System
When we run this we will see that we have two buttons using the same resource. It would just work for simple static resources.
Templates are designed as a mechanism to reuse the trees of object that include user interface elements or behaviors. The event handlers that we define in the templates will be hooked to the object each time it is instantiated. Templates are usually declared as resources and it is a shared object. A template is just a factory and each time we use it creates a new copy and gives it the object. Templates are usually defined to work in a particular context like the ControlTemplate works to define the look of a particular control and a Data Template will work to display the data in the specified format. To use the template in a particular format we need to use the raw template. Let’s see this in action. Add the following code to your WPF window and you will see that we have specified a ControlTemplate in the Window.Resources. We have instantiated the ControlTemplate with the help of the Control Base class. As Control is the base for all Controls and it introduces the concept of Templates in the Controls and it’s not abstract. A control does not have any intrinsic behavior so we have used it as a way to host the template. It is not the perfect way of using the template though. As you can see we have specified that the controls should not act as a focus control. If we do not turn off the Focusable then each of these controls will have focus twice.
Another way of fixing this double focus issue is by using a DataTemplate and a ContentPresenter. Add the code as shown below to a Winow xaml.
The best place to use data templates is when the situation demands it such as DataBinding or ControlCustomization.
Xaml File Reuse
We can also reuse the xaml by separating it out to a different file and we can use Application.LoadComponent to load the compiled xaml resources. The Application.LoadComponent creates a new object by reparsing the xaml or baml every time it is called. After loading the component we need to add it to the UI tree. The root of the xaml file can be any type and we can package any sub tree this way.
We can also use a Frame or a NavigationWindow to load the xaml. It’s really straight forward to load the xaml this way. All we need to do is point Frame directly to xaml file in the project and it will load a copy of the page. We can only point these to a xaml file whose root is a Page.
Xaml with Code Behind
In our application we can combine any xaml file with a code behind file. All we need to do is to provide the x:Class attribute which will define the code-behind class and we can use any WPF type as the root.
Let’s see this in action. Let’s create a reusable Grid with some behavior. Add the following xaml to a Page.
WPF Xaml + Code Behind
Now add the following code to the code behind of the GridComponent.
WPF Xaml + Code Behind
Now let’s try use this GridComponent which has a Button Click behavior,
WPF Xaml + Code Behind
Anytime we are defining classes with code behind, we are just creating partial classes and we can instantiate them with C# new operator or we can use xaml as shown above.
UserControl is name of the reusable UI component which is built from other components. As we saw in the last section that we derived from a Grid to create a custom control, generally in WPF we derive from UserControl. You should know that UserControl does not do a lot. We can take an approach similar to user control with any UI element. The main reason of the existence of UserControl is to have a recognizable base class. The only problem with using Grid as the base class instead of the UserControl is that the .NET programmers will expect the Grid base class to provide the same functionality a Grid does and that might be really messy because the Grid will break the rule that the derived class provides the same functionality as the base class. As a matter of fact the UserControl also breaks the rule of derived class. The UserControl derives form Control but still it does not provide the functionality for a Template because there is no way to hook up the look of the UserControl with the code behind. User Controls are not lookless controls. UserControl is derived from ContentControl. It does that because whatever control you put inside UserControl xaml it displays that. This means if we set the content of the UserControl then the complete content of the UserControl will be replaced. So we should not try to set its template or Content.
Limitation – A class only gets to use xaml once in its inheritance chain. Although we can inherit from UserControl, we cannot use the xaml because the UserControl base class has already used it and same is true if the class derives from Window or Page. A class gets to use xaml with code behind only once and the base class has already done that then we cannot do it again. To understand this you will need to understand how Application.LoadComponent works. The way it hooks up xaml with code-behind is incompatible with inheritance. There are two things that need to be hooked up at xaml loading time.
Named elements must be placed in their corresponding fields.
Event handlers that specified its attributes must be attached.
Application.LoadComponent does this by using the interface IComponentConnector. The code behind class implements this. So when the derived class tries to implement the IComponentConnector then its implementation replaces the one that was done by the base class.
Runtime XAML Parsing
We can generate and parse xaml at runtime. For example we have an application that returns xml documents then we might have to run these through xslt which will generate the xaml and we would parse and run this xaml. This parsing can be done through the xaml reader class. We can do this by passing the xaml string or by passing xamlReader object and it will return an object with the root as the xaml tree and that tree will be defined as the xaml passed. The restriction in this mode is that events will work. Also we will need to call the FrameworkElement.FindNamed helper method to find any named components.
Here are a few base classes that do not involve xaml:
Decorator – It is the base class for all the utility elements that contain a single child and provides some sort of service. The exact functionality of the decorators varies from a decorator to decorator. The border decorator provides the border around the child element whereas a viewbox applies a scale transform on the child so that the child takes all the space. A decorator and content control both host a child. The difference between them is that a Content Contol has some interactive behavior whereas a decorator does not.
Adorner – Adorners are visual elements that are attached to some other elements that always appear on top. As we can see in the image below that one of the grids is selected and all the resize, rotate, etc options available are all adorners. These adorners will be visible even when the object’s z-index in low and its not visible on the screen.
But an adorner decorator is the one which decides the bound of the adorner. So even when the element is sent back then also adorner is visible so you would think that an adorner is designed to be on the top at all times but when a panel comes above it as shown in the image below the adorner does not come above it. This is done with the help of an adorner decorator in the visual tree. S here an adorner decorator is defined as the parent of the design surface so that no adorner comes above it.
Panel – Panel is the base class for the WPF layout strategy type i.e. Grid, StackPanel,etc. If we want to write a custom layout we need to derive from Panel.
Shape – This is the base class to use when building any custom shape like a rectangle or ellipse. It provides Fill, Geometry cache, etc properties.
FrameworkElement – This is the base class to use when we are building a Code based user interface element and there is no other base class that suits our needs.
Custom Controls – This used when our UI elements has some distinctive behavior which is not provided by the controls available.
While building a custom control or a custom feature we need to consider the following things.
Properties – These are useful for components that are reusable from xaml as this is the API that does not require code and the functionality of the control will be accessible simply by setting properties. To use properties we need to use the WPF’s dependency property system so that the property supports Triggers, Animation, styling, data binding, notifications, etc. So there might be properties that do not do a lot in code but are controlled by the templates.
Events – These allow code to be run when things happen in your code. These also allow triggers to be hooked up into xaml. Defining a custom event is pretty similar to defining a property. We need to register the event and store in a public static read only field.
We provide event accessor. The AddHandler and RemoveHandler methods are provided by the FrameworkElement base class.
We need to raise the event by creating a RoutedEventArgs and passing it into the FrameworkElement ReiseEvent method. RaiseEvent requires the event to be of type RoutedEventsArgs or derived from that.
We can add a class level event handler for the built in events.
Commands– These are really useful in controlling the behavior of the elements as any operations that can invoked by commands can be driven by xaml. We can hook up controls like menu item or a button with commands. Commands are really straight forward. We just need to create a Command of type RoutedUICommand and provide a name, display name and owning type. Commands are made available as public static read only fields.
In order for a command to do something we need to register a command Binding. As we want each and every instance of the class to handle the command we should use a class level command binding instead of the instance level binding as the class level binding is slightly more efficient. To register the command we need to pass the static command name and command owner details to the CommandManager.RegiterClass method.
Control Template – While writing a custom control we need to decide how its template will work. We should define the control by defining the idioms for the control liked the named parts. This tells what the control expects from its template. We can list parts we require by specifying the TemplatePart attribute. We need to declare the name of the part and the type it should be compatible with. Let’s see this in action. Add a custom control to the project as shown in the image below.
WPF Custom Control
Now let’s use the NamedParts idioms to specify what we want in the template.
WPF Custom Control
The most important thing to do while working with templates is to override the OnApplyTemplate method as WPF will call this each time the control is given the template and this might happen multiple times. The first thing that we do here is check if the tenplate is not null and then we proceed to find the named part in this particular control. Then we cast it to the types of Shape. If the template named part is not null then we hook up a mouse down event handler and in this event handler we set the target fill property to green.
WPF Custom Control
Now, Let’s use this custom control in our application
WPF Custom Control
On MouseDown event the fill changes to green. So our handler works for the templates.
Most controls would want to have a default template. We generally do this by providing the compiled xaml resource by putting them in the themes folder. We should also provide generic.xaml to provide the resources that might be needed when the resources specified by the user are not available. Also the assembly must declare the presence of these themes by using the Assembly Info attribute. This tells whether theme resources are present and whether generic resources are present. As we can see in the image below WPF added this information when we added the custom control.
WPF also added a Generic.xaml when we added the custom control and this contains a style for the custom control that we added.
Let’s add one more instance of the custom control without overriding the template and we will see something like below. The functionality of both of them is same but the appearance is different.
We can integrate with design environments such as Visual Studio or Expression Blend. We can move all the general purpose design time code to a separate dll and we can follow the naming convention by adding .Design at the end of the class name. Or we can place the designer specific code in the dll with extensions .Expression.Design or .VisualStudio.Design in the end and if we install these dll so that they appear in the add reference panel then the designers weill be able to locate them.
We can put design time components in the toolbox for any design time environment. Visual Studio provide option to specify the Custom adorners or items in context menu or view or modify Object tree or property grid.
If we want use the design time dlls then the design time dll must include a implementation for IRegisterMetadata.
Any questions, comments or feedback are most welcome.
by Abhi·Comments Off on Learn WPF: Part 9 of 9: Text in Windows Presentation Foundation
In this section we will look WPF text formatting in layout services. We will have a look at text rendering feature, text layout services, text object model and text editing controls.
WPF uses ContentModel to present the text so WPF is does not just present the text as a plain string but allows you to take control and present whatever you want, so all the controls that use text are free to use WPF text formatting. As we can see in the image below we have used multiple fonts and color in the TextBlock inside a button. I know it looks ugly but the point is that this is the kind of capability WPF provides us with.
WPF Rich Text
As we can see in the image above we have placed a textblock inside the button. TextBlock is your control if you want to a few letters or a few paragraphs. It supports Font Styles like FontSize, FontFamily, etc. It also offers block level formatting options. But default a TextBlock only runs a single line display but if you want to display paragraphs you need to turn on text wrapping. We can specify the TextAlignment. Till now you have seen TextBlock accepting the strings as the Text to display. That is done for the convenience for DataBinding, etc. We can provide content model to the text to provide formatting to the other part of the texts. We have individual properties which will be used to provide formatting to text sections. There is also Span which can be used to apply a format to the span of a text. We also nest these formatting like a span inside a span. As use can see that we have painted the text with LinearGradientBrush. It is evidently similar to html. Though it might look like HTML these are objects and blend well with .NET.
Class Hierarchy for WPF Text Model
Inline Text Elements
In the image below we can see the class hierarchy of the WPF Text Object Model. These are the Inline elements of the text like the short runs of text that are within the paragraph like a bold or underline. As we saw in the Core Elements section that the most of the WPF Elements derive from the FramworkUIELements but Text derive from the FrameworkContentElement. As we can see TextElement derives from FrameworkContentElement and provides properties like FontSize, FontFamily,etc. The properties in other WPF Controls provides aliases to these properties. If you go to the Control.FontSize property of a control and retrieve its DependencyObject then you will see that it derives from TextElement. Controls just provide an easy way to use these properties rather than using the cumbersome attached properties syntax. Controls do this by using the static Add Owner method of the dependency property which allows an element to declare the use of attached properties as a local property.
Inline class is the base the class for elements which are designed to use within a paragraph. As we can see that these elements which are designed to use in a paragraph and the most of them then further derive from Span. Span defines a children property and Span can acts a container and that is why we are able nest these elements in XAML. LineBreak lets you add line breaks between paragraphs. WPF does not consider these as paragraphs from Content Model point of view. And since Paragraph is not an inline element and so we cannot use it as the inline element. So LineBreak comes in handy and it helps to design stuff inline that looks like a paragraph. Run is an inline element which we always use but never write it. Confused? Actually Run element is the only one capable of holding a string The Span is a content model that support only inlines. Run is automatically generated when we add text strings. Let see this in action. You will see that the run elements are automatically generated by the xaml compiler when the types request it.
WPF Inline Text
Block Text Elements
Blocks are paragraph level constructs like List, Tables, etc. Since these elements do not derive from inline we cannot put them into textblock so we need to place them into a FlowDocument that supports Blocks.
Document Viewer Controls
To display a flow document we need to use one of the DocumentViewerControls.
FLowDocumentScrollViewer – This displays content as continuous vertical scrolling. This one looks similar to a web browser page where we can place unlimited content and it will scroll vertically.
FlowDocumentPageViewer – This provides a paginating view. You can see it in lot of online reader like msdn reader. This will size the content to page according to the reading area available and font size so that no scrolling is required and it uses pagination for the documents that not fit one page.
FlowDocumentReader – This lets the user decide as to which FlowDocument style to use. This is similar to what we will get wahen we display a flow document inside a content control.
Paragraph is the simplest block type. It is just a collection of inlines and so we can fill it up with text or marked up formatted text. Since paragraph support inline contents it will wrap its content into run elements impliclitly.
Section is another block type. As the block has no intrinsic appearance of its own. The purpose of a block is to let us group several other blocks together and then we can set the text formatting properties on the entire block any text formatting applied to a section will imply on all the blocks of the entire section.
List block type makes it easier to display bulleted and numbered list. WPF provides just one list that does it all. The MarkerStyle property of the list will specify whether we want bullets or numbers. You can specify the numbers, letters or bullets. We can use only inbuilt bullets as there is no way to define the custom bullet types.
The table block element lets us build the table of texts. This may seem similar to Grid but the Grid derives form FramworkElemet and Table derives from FramworkContentElement as it is a text element. The table understands the text layout roots and this enables the table for doing what the grid cannot. Like a table can span multiple pages if it cannot fit one page. Also unlike the grid we do not need to tell the table upfront as to how many columns are needed. It generates them as per the content. The advantage of grid over table is that we can put multiple elements in one cell which is not possible in a table. We still can have nested elements inside a table cell though.
Figures and Floaters
Other inline types are Figures and Floaters. They cannot be used inside a TextBlock though. These can be use only in a FlowDocument. These let us place the content that is out of the main flow of the document like images, tables, etc. They support nested items of content and the main text will flow around them. These elements provide as an anchor point for content out of the flow of the document.
Floater – It is the simple of the two and we can provide the alignment of the element.
Figure – This is more flexible. It’s designed for paginated views. We can the content to appear at the top of the page, half of the width of the page or span a couple of columns.
Integrating a UIElement in a FlowDocument
We can do that by using the following:
This is like the textbox but uses the FlowDocument as its internal representation. So it uses the TextObjectModel we just explored. It can also import or export the rich text format through the clipboard.
Any questions, comments or feedback are most welcome.
by Abhi·Comments Off on Learn WPF: Part 8 of 9: Resources and Internationalization in Windows Presentation Foundation
In this section we will talk about Resource handling service of WPF and support for Internationalization
WPF provides a resource system for sharing resources. We already used this by using the Resources Properties of a FrameworkElement. Every resource has to have a key as the resource system revolves around dictionaries. The key interface is in the xaml interface defined x:key because xaml has intrinsic support for dictionaries whether it’s WPF, Silverlight or anything else. So the dictionary key attribute lies in the common xaml namespace that lives in all dialogs of xaml. The resource system is used for designing objects for multiple use. It includes templates (factory like objects), graphical resources (especially the ones derived from freezable base class like geometry, transform, brush, etc).
Below we see example of different types of resources put into the resource dictionary. We have defined Color, SolidColorBrush, ControlTemplate for Button, ObjectDataProvider, .NET String, Array of strings and Button resources. All the other resources are fine but the button resource that we have added will give us an error when used at more than one place. A button is not built for sharing.
The resources property is present at various places in WPF. All FrameworkElement and FrameworkContentElement offer it. We can also add resources to the application object, styles and templates. In all the places it is defined the definition is same. It is of type resource dictionary and from the point of view of code it looks like any dictionary object. As it implements IDictionary and it lets us add any object for value and any object for value. In a way the behavior is different from the dictionary and sometime lead to runtime error. Each time we load the ResourceDictionary from XAML then each item xaml gets parsed for the first time it’s fetched. This means the creation of object happens when the key is accessed for the 1st time. So this improves the startup time of the application as the objects that are needed are the ones that are created. The problem is that you might get the xaml loading errors much later than expected so the xaml might seem fine at compile time and might shoot error on loading.
Xaml provides two markup extensions for using a resource.
Static Resource – It is a onetime lookup
Dynamic Resource – It works more like data binding. It remember that a particular property is associated with a particular Resource Key and if the object associated with that key should change then dynamic resource will update the target property.
Let’s see this in action. So here we have two rectangles which are associated with the same resource SolidColorBrush but one of them uses it as a StaticResource and the other one uses it as a DynamicResource. At the button click we will change the value of the SolidColorBrush and we will see that the Fill property that uses the resource a dynamic resource will change the property.
WPF Static Dynamic Resources
The difference between these two resources is clearly visible when we see the C# equivalent of these. The StaticResource implementation makes a single call to the FindResource method and sets the element property to the returned value whereas in the DynamicResource implementation is similar to SetBinding call done for DataBinding. Like DataBinding it will detect change and respond to them. As the underlying target property is attached to the reference of the resource. Now it’s obvious that the StaticResource is more lightweight than DynamicResource as it no tracking to do.
Each FrameworkElement in the tree can have its own local ResourceDictionary and that’s the first place where WPF will look for resource. If the resource is not present in the target element’s ResourceDictionary then it will look in the dictionary of the parent and then parent’s parent and so on till the root element followed by the application resources.
Whenever we create a WPF application it adds an app.xaml file. This let us configure the application resources.
WPF Resource Hierarchy
WPF provides System level resources. System resources consist of machine wide resources of logon session resources. But that’s not how it’s implemented as WPF is not allowed to share resources across process boundaries. So what happens is each WPF process gets its own copy of the system resources and all these copies are kept in sync across all WPF apps in session. Let’s see this in action. We have set the Fill color of the rectangle to be Highlight color of the SystemColors. But as you see the key for this DynamicResource is a bit different as we have used objects to uniquely identify the resource and these key objects are available as static objects. Also we have one DynamicResource reference and one StaticResource reference. So when we change the system color then we will see that the fill change.
WPF Resource Hierarchy
The SystemResource also contains default styles for controls. This is where the controls get there default appearances from. So we want to override the system resource values then we just need to provide the resources with the same key in our application and we can change the default style of the controls.
Alternate Reference Syntax
Just like all the markup syntax we do not mandatory need to use the curly braces syntax. We can use the property element syntax and spell out the markup extension as a full xml element. I am not sure how much will this be useful as you are using a resource reference at a place where you can’t use an attribute. In the example below we have used a static resource as the content of an element. The important thing to note here is that we need add the resource key through the ResourceKey attribute and normally we use the resource key to the markup extension as a constructor argument.
Implicit Resource Usage
Sometimes we use resources without resource key references. If we associate a DataTemplate with a type then WPF uses the ResourceSystem to locate that template. When a control with the ContentModel goes looking for DataTemplate for its Content object it builds a special kind of key object called as the DataTemplateKey to identify DataType and it is this key that is passed to find the resource. If we have added a DataTemplate to the ResourceDictionary in scope then it will find this DatTemplate because DataTemplates are self-keying types. So the key in the resource is hidden but it’s there. Styles also work in a similar fashion. If we specify a target type for a style then we don’t need a key. Also the styles can use the Type as the key. Apart from Style and Data Dictionary if we define any other resource without a key we will get an error.
Most WPF applications end up having a lot of resources and hence the xaml might look cluttered and unmanageable. So WPF Resource System provides a way to merge multiple resource files into a single logical dictionary. The resource dictionary class has a MergedDictionaries property to enable this and we can point this to any number of resource dictionaries.
As we already know that we cannot use the same resource key multiple times as it will lead to error. But it works a little differently in ResourceDictionaries. If a resource is not found in one resource dictionary then it is looked for in the next resource dictionary and so on. If the resource is found in one dictionary then WPF stops looking for it no matter whether its present in the other dictionaries or not. This has it pros and cons as you may imagine.
So we have seen WPF object resources defined in the xaml. WPF also supports binary resources in respect to bitmaps and videos this builds on .NET handling of binary streams. There are 3 ways of handling these binary streams:
External – The resource can be completely external to the application like an image on the web accessed with url or an absolute path on disk.
Loose – These are the resources that are present in the same directory as executable. These are files that are associated with the application and will be deployed with the application by the installer.
Embedded – The resource stream of these resources is embedded inside the exe or dll.
We still need to make a choice between the Embedded and Loose resources. The exact action depends on the build choice we make. There are 3 common ways to embed an stream as a resource. The oldest and last item on the list is Win32Resource which used by WPF for the icon which is shown in the Windows Explorer. We generally would use Resource or EmbeddedResource as a build action property.
Let see these in action. So we have a project with 2 bitmap resources. One marked with build action as a resource and the other one marked with build action as an embedded resource. Now if in the image object in xaml we refer the image file marked as a resource then we are see it.
WPF Binary Resources
But when we use try to access the Embedded resource then WPF is not able to find it. The reason is that embedded resources work differently. TO see what’s going on we need to have a look at ILDASM.
WPF Binary Resources
ILDASM is the disassembler for the .NET code and is part of .NET SDK framework and is used to look at the compiled IL for the assembly. It also shows the information about the resource streams. So when we open the manifest and scroll down we see the mresource part which is the resource stream.
So we see the WPFResources.EbRes.jpg as the resource stream. And the Res.png is in WPFResources.g.resources.
We have accessed this image in the code behind by getting the reference to the assembly then getting the stream of the embedded resource file.
WPF Assembly access
So this means the Embedded Resource works but it’s just not supported by image element directly.
Now if we open our application with the reflector we can see our embedded resource and also we will see that we always have a .g.resources file which has the resources and .baml files. Baml is Binary Application Markup Language. It is the Binary Format of the xaml which has the elements, texts, etc. That is how all the WPF xaml ends up i.e. as a compiled baml stream inside the resource collection alongside any resources with Resource BuildAction.
WPF uses the Resource Manager so that we can provide the compiled versions of our xaml files, resource file sin different languages. WPF ResouceManager does that by packaging them up as a satellite assembly and then deploying them next to our application. So WPF prefers to use the WPF Resource BuildAction.
So below we can see the examples of the WPF Image Resource Uses.
Application Class Resource Methods
WPF Application class provides some helper methods to work with the resources.SO if want to get a stream in the application then we are supposed to use the Application.GetResourceStream method. And use GetContentStream for loose resources and GetRemoteStream for remote resources. We use these helper so that we do not raise any security exceptions in the limited access application. So we should use these helper when we need direct access to the resources. Another helper LoadComponent is used for compiled xaml. As we already know that xaml is compiled to baml. We should also remember that all .NET applications use LoadComponent to load this baml.
WPF support for VisualStyles or Themes lies in the concepts we have been looking at. These are resources that are compiled as resources as compiled baml streams. According to naming conventions their names all start with Themes\ and the resource streams will be compiled into the folder called themes and then we have one compiled xaml stream for themes. As we can see in the image below
All the controls provide themes in this way. WPF controls do it this way and custom controls do it this way and these resource strings just get added to the system resource scope. WPF selects the appropriate resource stream based on the theme we are running and just merges its content into the resource scope. If we do not have resources matching the current theme then WPF will look for Generic.xaml as a fallback. That’s where the control library will put a set of resources in the event the user is using a theme that the control did not know about.
Internationalization depends entirely on the resource manager. If we want to localize an application for a particular culture then we need to provide a satellite resource assembly for that locale which contains the resource stream with the suitably compiled version of the xaml.
The process that is followed is that the Code behind calls the InitializeComponent() which in turn calls application.LoadComponent. LoadComponent will then use the ResourceManager Infrastructure to load up the baml stream and the ResourceManager always checks to see if the satellite resource assembly exists of the current locale. If the suitable assembly is present then it will look into the resources to see if it contains the localized version of the baml. And if it does then that baml will be used instead of the one compiled into the main assembly. SO localize the application we need to make the necessary changes to the xaml and the compile that to the satellite resource assembly and then deploy that to the appropriate sub directory for the culture and that’s all. But in practice we will not have a xaml file for each language so we will have one master xaml and then derive the xaml for individual languages from that.
So the runtime model is different from the production model. So at runtime there is a compiled version of a xaml file for each language and at runtime we try to have one master file and then generate the different files from that.
WPF provide tools to support a particular workflow to the localized resources of the application. We will start with one Unlocalized for the XAML resource. The first that we need to do is add Uid annotations which provide an unambiguous name to each element. As we have already observed xaml elements may already have names so why do we need another one. The reason is that xaml x: namespace has 2 problems:
It’s not necessarily unique
So it’s easier to have unique names just for the purpose of localization. WE can add matching Uid with WPF build targets so that MS build can modify the files for us adding the necessary uids.
Then we build the project as normal producing the binary with embedded compiled xaml.
Then we run a tool to extract all the information that may need to change for localization purposes. The tool that Microsoft provides puts it into a csv file. That is a , separated value file. Also we can modify the tool to configure the way we want to use the tool.
Then we work out what needs to be changes for our target culture and make a list of the same. Again the MS tools work with the csv representation but we can modify the tools.
Then we can use this to produce the localized version by running it against the tool that sees the differences and generates the files.
So the output is a satellite assembly which can be deployed alongside the executable.
The tool provided by Microsoft to support this is called LocBaml. We actually have to build it ourselves as it is a sample in the sdk. So it does everything the code supports. It uses documented API .So the process is supported even if the tool is semi efficient. As localization tends to be somewhat specialized operation a lot of companies rely on external companies to do the translation. But WPF aims to provide the mechanism rather than the tools to do the localization.
It is not necessary that we follow the same workflow provided by LocBaml. We can use DataBinding for this purpose as well.
XAML presumes that UTF is the default.
Any questions, comments and feedback are most welcome.