Understanding Templates - wpf

I'm struggling with Templates in WPF
I understand the concept in that I can have a control, and 'override' the ContentTemplate (or similar). I use it often with the TabControl
However, I don't understand it in terms of what the initial control looked like. And if we are limited on the names. EG, could we build a control and overwrite the NonsenseNameTemplate?
If I were to build my own UserControl and provide the ability for people to override things like my NonsenseNameTemplate, what would this code look like?
My guess, with pseudo code would be
<UserControl>
<NonsenseNameTempalte>
//some resources
//some other controls
</NonsenseNameTempalte>
</UserControl>
In the above example, I can fully understand how I could create a new control and overwrite the NonsenseNameTemplate but I can't see any code examples of the UserControl and it's usage.

Template is nothing more than a (dependency) property. By writing
<Button>
<Button.Template>
<ControlTemplate>
...
</ControlTemplate>
</Button.Template>
</Button>y
you are doing nothing more than creating a new instance of ControlTemplate class and assigning it to Button.Template property of that specific button. Each control has it's own ControlTemplate saved somewhere in it's assembly. It is generally not so simple to actually get those default templates, but Blend can help with it.
Of course, you can create your won NonsenseNameTemplate property, but actually using it would require some deep knowledge of WPF composition, layouting and rendering. Which is usually not required for normal usage of WPF. And I agree that there is not a much online resources about doing something like this, for exactly this reason.

I too had an early on learning of Templates. I posted a step-by-step answer to another question via a customized button control. The nice thing about that sample, you can build and play with styles and templates in a small project and see visual impact without requiring full project rebuild

To start with, as you have mentioned that you do not have Blend. You can have Blend and install it with Visual Studio 2013 Community.
You can download this here if you do not have it already.
http://www.visualstudio.com/products/visual-studio-community-vs
A part of the installation process, it allows you to select and install Blend. Also, the newer editions of visual studio give you some of the power of blend. In your design view you can right click on a control and create or copy a template.
On to the question.
As Euphoric has mentioned. Custom control authoring does require a little more in-depth knowledge of WPF, or any of the XAML frameworks. However, there are Visual Studio templates that can help you in the right direction.
As for the template naming, you have three types of templates you will come across in XAML. ControlTemplate (which for your purposes is the one we are interested in), ItemsPanelTemplate and DataTemplate. Again, as Euphoric has said, there are few circumstances where deriving a custom version of any of these three templates would bring anything to the table.
If you were to create a test WPF application, once you have created the basic project and solution. Go a head and add in another project, and from the templates VS provides, File -> Project -> New -> Windows Desktop. In the project template list, find 'WPF Custom Control Library'. Once created, reference this project in your main WPF project.
This custom control library project will give you a skeleton setup for what you are looking for.
If you look in this project here are some things for you to note.
Firsty, you will find a folder called Themes and in there a file named Generic.xaml. In there you will see a style that has a setter setting the Template property. You will also see that both the Style and set ControlTemplate have a set TargetType that should be local:CustomControl1.
This is important as this is showing you how to create a custom controls default template. Now, to apply this template look in CustomControl1.cs and consider the following code.
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
For this control named CustomControl1, that template we looked at in the xaml will be automatically set as that controls default template where ever that control is used.
This project is a good starting point. But now you may want to override this ControlTemplate inside your main project. This is simple. I have code that looks something like this inside my main WPF project.
At the top of the MainWindow.xaml
<Window x:Class="CustomControlTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CustomControl="clr-namespace:CustomControlTesting.CustomControlLibrary;assembly=CustomControlTesting.CustomControlLibrary"
Title="MainWindow" Height="350" Width="525">
And in the body,
<CustomControl:CustomControl1>
<CustomControl:CustomControl1.Template>
<ControlTemplate TargetType="{x:Type CustomControl:CustomControl1}">
<Grid>
<!-- Define my look to override the template -->
</Grid>
</ControlTemplate>
</CustomControl:CustomControl1.Template>
</CustomControl:CustomControl1>
This is a brief overview and certainly misses out a lot. But I hope this is of help to you and can get you started.

Related

What would be a good approach for several Silverlight applications with common controls?

I'm pretty new to Silverlight and have to code several SL applications which will share many things.
I plan to put all common C# code in a separated assembly but I'm really annoyed about the XAML part.
All my applications will have some common controls:
a menu bar at the top,
a toolbar at the top,
a status bar at the bottom,
a panel on the left.
I searched the web for hints and discovers that XAML code cannot be inherited.
So I thought about creating a big custom control containing my common controls and then adding it on the main page of all my applications but that doesn't seem to be the right way.
What's the best practice, here?
Any help appreciated,
EDIT: What I'd like to get here, is something I already did with WinForms. I created a "base" WinForm and put some controls on it. Then, when I created new WinForms which inherited this "base" WinForm, they had all the basic controls. I didn't have to use any custom control.
But I understand that Silverlight is not WinForm and what I want might not be feasible this way (or at all?).
It depends on the route you want to take, whether you want to make one resources file with some templates etc, which is copied/linked into each application seperately, or use something included in a common DLL.
If you want to do the latter, here's one approach. Subclass ContentControl to define your common layout in its control template (you can do this all in XAML), including a binding to its Content in the appropriate place:
<ContentControl x:Class="MyLibrary.MyLayoutControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<!-- this could be a layout grid with various other controls in it -->
<Border BorderBrush="Red" BorderThickness="2" CornerRadius="5">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
Then use it in your application root control:
<UserControl x:Class="InCustomControlTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:MyLibrary;assembly=MyLibrary">
<c:MyLayoutControl>
<Button Content="Hi I am a button" />
</c:MyLayoutControl>
</UserControl>
If you want to do something more sophisticated, you should make a custom control; though in most cases you may instead be able to get away with a few UserControls for various components (eg your status bar) that you drop into the right place.
There is no big problem putting xaml resources in library projects.
When referencing resourcedictionaries from other projects, be sure to include the assembly name.
Also there is inheritance on templates, where you can put BasedOn attribute.
Edit: well, looking at the project we worked on some time ago, I now remember we actually had problems with it and had the xaml resources copied to each project... I forgot =)
I think it worked but brought some problems here and there. Maybe add the xaml files as links?
Personally I would also not create to many controls, rather have templates for most stuff. If you have controls, better write them in c# only with usage of templates, preventing xaml with code behinds. Just my personal experience, might not be the common guideline.

How can I discover WPF resources defined in another assembly?

I'm writing some extension modules for a WPF Composite application supplied by another vendor. The application is themed, and gives users the option to select from a number of themes which will change the appearance of the entire applications, including any custom modules that register themselves with the theme manager appropriately.
I really want my custom extensions to look like an integrated component, so I'm trying to use only styles defined as resources within the main application. As I'm still learning the nuances of XAML, I'm styling more by trial and error.
I'm wondering if there's a way of 'discovering' what styles are available in a different assembly. Here is an example of what I'm currently doing.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<common:DesignTimeResourceDictionary Source="/Vendor.Desktop.WPFCommon;component/themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Border
Background="{DynamicResource LightGradientBackgroundBrush}"
Margin="0"
>
The LightGradientBackgroundBrush is defined in the vendors assemblies. By including the above ResourceDictionary, the style is present during design time, and the brush isn't underlined in the XAML editor.
Can I find what other styles are defined? I'm only aware of that style because it was mentioned in passing in a sample provided by the vendor.
Edit:
I'm aware of a BAML add-in for reflector, but it doesn't work with reflector 7 unless it has been recompiled/patched. Someone has already done that here though.
I was hoping there was a better solution though. Intellisense for styles would be great.
There used to be a Reflector add-in for viewing BAML resources that worked well for that. But I haven't used Reflector in a while since Redgate crashed the party. It may not work with the current version.
You know where your resource dictionary is so you should be able to load it up in code and enumerate over the available resources. This will at least give you an idea of what's available.
See this link: http://blogs.claritycon.com/leeroth/2009/05/20/load-xaml-resource-dictionaries-at-runtime/
Enumerate over the Keys property and use the item property to access the resources. You can get as detailed as you want, but at the very least you should be able to spit out the resource names.

How can I load a WPF theme?

My understanding of the difference between a WPF theme and a WPF skin is the following:
A WPF skin is a set of resources loaded by an application.
A WPF theme is a set of resources handled by the OS.
To load a skin, I can just call Application.Current.Resources.MergedDictionaries.Add (mySkin);
However, I don't see any way to load a theme.
Is this documented or available?
Should I access the System.Windows.SystemResources internal class?
You can load them as a ResourceDictionary:
<Window
x:Class=”TestProject.Window1?
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>
<Window.Resources>
<ResourceDictionary
Source=”/presentationframework.aero;component/themes/aero.normalcolor.xaml” />
</Window.Resources>
</Window>
Note: You would need to have a reference to the PresentationFramework.Aero.dll.
There's quite a subtle difference between Skins and Themes, and the reason why you're having problems with what you're trying to do might stem from this:
In WPF, a theming and skinning takes
on slight variations to their
meanings. Theming refers to
controlling the look and consistency
of an application UI to match the
operating system. For example, a WPF
application can be themed for the
Windows Aero theme or the Windows
Classic Theme. Skinning refers to
changing the application's appearance.
In other words, applying or letting
the user pick a skin to change the
look and feel of the application.
Robby Ingrebertsen, while working on
the WPF team, simplifies it as
follows:
Around here, we generally say that "theming" refers to the system theme
and "skinning" refers to changes to a specific app. This has helped to
clarify our internal communication
From here
So essentially, if you want your app to look like one of the Windows themes,ie the current windows theme - you don't have to set any styles in your app and it'll chose a pre-defined XAML skin that resembles it automatically. But, if you want to style your application, you make a skin for the app as you're doing.
As far as loading the Windows themes, this answer might help
(Answering my own question)
The way to load a resource dictionary as a theme is to add it to the list of merged dictionaries of the generic.xaml resource dictionary.

Resource Dictionaries in a Silverlight Assembly?

I've just begun dabbling in putting together a set of controls as assemblies and I'm working on default styling. What I currently have is a UserControl in a project (thanks Reed!) and I'm able to bring that into another project via reference. I plan to add more controls over time to build something of an SDK.
I currently have some hooks that look for resources in the hosting application which either apply the resources to their respective properties, or style out the control via hard coded defaults.
Is it possible to set up resource dictionaries within the project containing the UserControls so they can use those references as the default, instead of hard coding? If so, how do I target them?
(I have a ResourceDictionary set up within the same project as the controls: Resources>Dictionaries>Colors.xaml)
Thanks in advance!
E
You should really look at creating custom templated controls in library rather than derivatives of UserControls. This will allow projects that reference your library to specify an alternative default style for you controls in the same way as we can for the controls in Microsofts own SDK.
The Creating a New Control by Creating a ControlTemplate topic on MSDN is good starter.
I think this is a better explanation, but i'm trying on a desktop application and i got the same problem.
XamlParseException: Failed to create a 'System.Type' from the text 'local:CustomerEntity'
If I'm undestanding correctly you want to create the file "generic.xaml" in the folder "Themes". However, I don't believe automatic styling works with UserControl only with Control. Generally if you trying to make a control that can be stylized and retemplated you want to inherit from Control and not UserControl.

Custom Controls with Blend

I'm building custom control for my Silverlight 2 app. It's in one SL class project, and it contains two files:
MyControl class, inherited from Control, with few DepedencyProperties
themes/generic.xaml, with visual elements (ControlTemplate), states for VSM and transitions
I created whole xaml by hand, and it works, but want to use Blend2(SP1) for editing! When i open generic.xaml in Blend, and switch to Resources tab I don't have anything to edit.
For example, when I put that visual template and states definition to App.xaml (of my main SL project), I can access all elements and States through Resources and States tabs, and edit them visually.
Does Blend even support editing generic.xaml from SL2 class project?
What's the best practice for building custom controls? I don't want to my custom control depends on anything from main SL2 project, but want them to be skinnable, and be able to change skins (themes) dynamically.
You can edit this with Blend.
Open your controls project in Blend.
Open your generic.xaml
click the Resources tab
Expand generic.xaml
Double click the style resource you want to edit.
In the Objects and Timeline section, right click the Style and select "Edit Control Parts -> Edit Template"
Now you can edit the template in the generic.xaml. Sounds like you're already following best practices by having the parts and states. If you want the full blown best practices take a look at this detailed post on how to deal with design time extensibility. There you will find out how to do the Visual Studio and Blend design time stuff for Silverlight.
I recreated whole project, and suddenly can edit my generic.xaml from Resources. But can't add news stated in Blend, for that I must go to xaml.

Resources