wpfdatatemplatecontroltemplateavaloniaitemspaneltemplate

How to discover template


I've been struggling with Avalonia and WPF for a while now and I just don't seem to get it. Specifically, I don't get templates. I don't understand what "level" to instantiate a template, and how to even know what templates are available. This WPF is not "discoverable" to me at all (to borrow a UI/UX phrase).

For example in this SO post: How can you add Children to an ItemsPanelTemplate of an ItemsControl in WPF?

There are three different types of templates shown:

When trying to come up with a graphical representation for some custom data structure, how am I supposed to know which template to use? It all seems quite ad-hoc to me and I haven't been able to figure out the underlying rules or patterns to guess when a template might be available and how to invoke it without having to go find an example someplace.

What am I missing? Can someone explain the big picture, or point me where I may become more enlightened about this?


Solution

  • Long Story Short (TL;DR)

    When trying to come up with a graphical representation for some custom data structure, how am I supposed to know which template to use?

    You would create data templates for your data types. The key differences are:

    Short Story Long

    Misconception

    I don't get templates. I don't understand what "level" to instantiate a template, and how to even know what templates are available.

    I think your mental picture of templates misleads you. There are different types of templates that serve different purposes, not levels. These template types are neither part of a hierarchy, where one supersedes another, nor are they interchangable.

    Control Template

    Purpose

    In the following, by control we mean the base type Control or a type that is directly or indirectly derived from it, like Button, ComboBox or TextBlock. Let us pick Button as an example to see how controls are designed. A button has different states like Mouse Over or Pressed and can be clicked to execute an action. These states are implemented as properties IsMouseOver and IsPressed and the signal that it is clicked is exposed as Click event and so on. Now you have a fully functional button, but no graphical interface to interact with.

    This is where control templates come into play. They define the visual representation and behavior of a control. Please note the word visual, because that is the key point of templates, to decouple the logic or core of any control from the way it is displayed. What we mean by visual behavior is what a user experiences when interacting with the control. You could decide that a button changes color when hovering over it with the mouse or you could flicker it. This is also part of a control template specified in various ways, including animations, triggers or visual states.

    But why? In the past UI frameworks were often written completely in code, e.g. C++, not using markup languages like XAML. Controls were drawn in code using drawing primitives or pixel by pixel. Visuals, behavior and logic were baked into a type. In order to adapt visuals or interaction, you would have to derive a custom control and draw it yourself or you wrote controls from scratch. This is cumbersome and harms maintainablity, as well as flexibility.

    Looks are Subjective

    There are many reasons why you would change the visual representation or behavior of controls:

    Instead of deriving a new button for each case, you can now simply define a control template for each in XAML. You would still have a single button type, since its implementation never changed.

    Definition and Usage

    A ControlTemplate is usually defined in XAML within a Style, directly assinged to the Template property of a control or put into a resource dictionary and referenced where needed, but it can also be built in code.

    Summary

    A control template helps to separate the logic or core of a control from its visual representation and behavior. WPF provides styles and control templates for built-in types. If you want to change the visual apprearance or behavior of any control, write a custom control template for it.

    Guidance for You

    Create a control template for a control if you author custom controls or themes or if you want to customize the visual tree of a control in general, including changing is visual apprearance or behavior. Each built-in WPF control has a default style and control template described here.

    Resources

    Data Templates

    Purpose

    As its name suggests, a DataTemplate is a template for data. Data is any structure you define that carries information, e.g. a Person class with name and date of birth, maybe even an image. Now we face the same issue as for controls: How to visually represent these data? Do we want to bake UI controls into our data models? No, we want to decouple our data from the way it is displayed, since those are completely separate concerns.

    Looks are Subjective Again

    Again, instead of copying, deriving and coupling your data to views, you have a single data type and multiple data templates, each tailored to a specific information need and scenario.

    Definition and Usage

    A DataTemplate is usually defined in XAML and assinged to the ContentTemplate property of a ContentControl (single item) or the ItemTemplate property of an ItemsControl (multiple items) or put in a resource dictionary and referenced where needed. You can define it in code, too.

    Within a data template, you use bindings to reference data. Please be aware, that your data type needs to implement the INotifyPropertyChanged interface, otherwise bindings will not be notified when a property changes. For collection properties, use OberservableCollection<T>, otherwise changing the collection by e.g. adding or removing items will not be notified to bindings either.

    Special Case for Hierarchies

    Data can be hierarchical, like employees as part of a department and departments as part of a company. For this case there is a special type HierarchicalDataTemplate. It is used in the TreeView control. It is just the same as a regular data template with the exception that it allows you to specify a child items source via its ItemsSource property and also a child data template via its ItemTemplate property. Think of it as if you would nest multiple items controls, but through a template instead. This allows homogenous as well as heterogenous data hierarchies to be displayed individually.

    Practices to Avoid

    Data templates are for data and control templates for controls. Technically you can write a control template instead of a data template and nothing can stop you from doing it, not even the desperate screams of WPF developers bleeding from their eyes. Never do that. Say it.

    Summary

    Data templates separate your data from their visual representation.

    Guidance for You

    When trying to come up with a graphical representation for some custom data structure, how am I supposed to know which template to use?

    This is exactly your case. Whenever you use or create a data type that needs a custom appearance or behavior in the user interface, create a data template. If you want to reuse it in multiple places, put it in a resource dictionary and include it in the application resources or locally where needed. If no data template is defined, WPF will display the result of the ToString method by default.

    More Complex Scenarios

    If you ever run into a case, where you want to create a complex control for your data, e.g. an input mask for a Person requiring custom logic that cannot be expressed by a template only, consider creating a UserControl or a custom control from scratch instead.

    Resources

    Items Panel Template

    Purpose

    An ItemsPanelTemplate is a very specific type of template only applicable to ItemsControls. It is used to change its Panel. A panel controls how the items within the items control are arranged, sized and ultimately rendered.

    WPF provides multiple panels for hosting items, e.g.:

    Each of these panels displays items in a distinct way. A StackPanel places one item after another, either vertically or horizontally. A WrapPanel places them in a line and overflows to the next line, if there is not enough horizontal space available. A Grid lets you define a tabular layout.

    Please be aware that some controls use a virtualizing panel by default in order to improve performance. Most panel in WPF are not virtualizing and could cause issues in these cases.

    Even Layouts are Subjective

    By default an standard ListBox would stack items vertically. This is not desireable in all situations. Maybe you want to display them in line with overflow, like a WrapPanel does. In order to change that, your would have to derive the ListBox and override methods to create your own, custom one, although nothing really changes, except for the layout. This would be bad in multiple regards and is the reason why all ItemControls provide a way to exchange the items panel without altering the control itself.

    Definition and Usage

    An ItemsPanelTemplate is usually defined in XAML within a Style, directly assinged to the ItemsPanel property of an ItemsControl or put into a resource dictionary and referenced where needed. It can also be defined in code.

    Summary

    Items panel templates are used to change the Panel of an ItemsControl.

    Guidance for You

    Create a custom ItemsPanelTemplate, if you want to change arrangement of items displayed within an ItemsControl by using a suitable Panel, e.g. one of the built-in panels.

    Resources