How is a a ControlTemplate instantiated in XAML? - wpf

In code a ControlTemplate contains a hierarchy of FrameworkElementFactory that can be used to construct the framework elements themselves. But, in XAML, a ControlTemplate's content appears as the elements themselves.
Does the XAML parser convert from one object form to the other, is a ValueConverter used, or does it actually create the factories as it parses the ControlTemplate content?

It is actually done differently, if it's defined in XAML versus in code. To verify, you can create a simple project in WPF with a single Window and add a custom Control that has a ControlTemplate defined in XAML by it's default Style. Then add the control to your window and add a Button, whose Click handler includes a breakpoint.
When the breakpoint is hit, we can inspect the custom control and it's ControlTemplate. The VisualTree property (which is FrameworkElementFactory) is null.
Using Reflector, we can see the relevant code in the StyleHelper.ApplyTemplateContent method. The first if-statement in that method, applies a FrameworkElementFactory (which is passed in from the VisualTreeProperty). The second if-statement loads the ControlTemplate from XAML, which ultimately executes FrameworkTEmplate.LoadOptimizedTemplateContent.

Related

Overriding a property within a ControlTemplate

I have a very large ControlTemplate (200+ lines) with many nested controls inside. I need to reuse this template with a small change to one of these nested controls (visibility of a checkbox). Obviously I don't want to copy-paste into a new ControlTemplate and just make that change because I'll double the code base and if I make a common change to the template I'll need to change both.
I've thought of three solutions that seem like they may work, but I don't know enough about XAML (and especially refactoring XAML to know if these are possible)
Extract the common XAML into a base ControlTemplate and 'override' the checkbox visibility in two new ControlTemplates (I place the override in quotations because I'm using C# speak - I've no idea if that makes sense in XAML!)
Gain access to the checkbox (via x:Name or x:Key maybe) from outside of the ControlTemplate definition, then setting the Visibility would be trivial.
Specify some kind of binding on the Visibilty in the ControlTemplate, something like:
<Checkbox Visibility={Binding someNewPropertyOfTheTemplate}/>
(Is this what TemplateBinding is used for?)
Are any of these ideas valid? And if so, which is the most appropriate? (If not - what is the correct way?)
I'm using VS2010 with .Net 4.0.
I would go for #3. But your code is not quite correct. If you want to bind to properties of the actual control, on which template is being applied, you should use TemplateBinding. Suppose you have a custom control with a property ShowCheckboxes. Then in your template you should use
<Checkbox Visibility={TemplateBinding ShowCheckboxes,
Converter={StaticResource BooleanToVisibilityConverter}}/>
Note, you may have to reference or create appropriate converter.
On the other side, if you use MVVM, you may define your control property on the viewmodel class. Then you should use {Binding}.
Also, there is another way to control which templates are applied.
You may extract the template for your subcontrol out of the big template. And copy it, so you have two templates, that differ in the way you need.
Then, in the main template you can set TemplateSelector for your subcontrol to the custom class, that you will implement. Look at the http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx for more examples.

Do I have to create a custom control as lookless?

I am creating a custom control derived from the one of the Standard WPF controls. The control has several constituent parts,and I am only modifying one of those parts.
Here's my question: If I am modifying only one part of a control, do I have to declare the control as lookless and reproduce the entire control template for the modified control in Generic.xaml, or can I omit the lookless declaration (found in the static constructor provided by Visual Studio) and simply modify the control template for the part I am extending?
I have tried the latter approach, and my control template is being ignored. I would like to get confirmation before I reproduce the entire control template, since what I am extending is the WPF Calendar. Thanks for your help.
It sounds like your best bet is to paste the entire template and modify the parts you need, although you didn't say exactly what you want to do or post any code.
Obviously if what you want to change about the calendar has a property you can modify in xaml, then that is easier. The opposite extreme would be to create a custom control (subclass).
I wanted to change the color or the ComboBox arrow the other day and the easiest way to do that was to past the entire template into a style and apply as needed, after changing one single part of the template (the arrow color, of course). There is no exposed DP to change for this and I didn't need anything more complicated than that.
HTH,
Berryl
The declaration that's generated for you by default is simply allowing for a default implicit Style to be defined for your control instead of just taking on the default Style of the base type.
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
What makes a control lookless isn't any specific declaration but rather it's definition in a code file which will then have some ControlTemplate applied to it at runtime. The alternative is the UserControl style of declaring a XAML+code-behind class which compiles into a single class with both UI and logic.
A simple example: Button is not the thing you see on the screen and click on; Button is a control that can take a single piece of Content and translate a user click into a Click event or Command call. What you see on the screen is just a visual template on top of Button's inherent behavior and state.

Templates in extended Silverlight controls

i am looking to extend a third party control, it is a ComboBox (so it isn't the standard Silverlight one, but that shouldn't matter for this question). To do this, i add a new template control to my controls project, then i change the new control to inherit from ComboBox instead of Control. A style has been created for me in the generic.xaml file, so i delete the default border stuff that was inserted, and then add a property setter for the PopupTemplate.
My problem is that when doing it this way, the combobox doesn't (visibly) render in the silverlight application anymore. However, in the constructor of my extension if i comment out the line
this.DefaultStyleKey = typeof(MyComboBox);
and put the PopupTemplate xaml bit in the main silverlight page, it renders correctly. I want the popup template to be declared within the control library, but does this mean that i also have to define the regular Template property? Am i wrong in thinking that anything i don't explicitly specify should just be inherited from the base control?
A control can only have one default style. You need to copy the entire default style of the base control into the Generic.Xaml for you new MyComboBox then adjust it accordingly.

Overriding method of an element within a XAML UserControl?

I have a Silverlight user control that has no template and does not need one as it is simply a path with a RectangleGeometry that is resized by code. Now our designed has added a template to the tooltip of the path and I want to be able to provide a method for users of the control to change the layout of a portion of this template. If the template was part of an overall one for the control I could simply override the control's OnApplyTemplate method and grab a reference to the section I want to modify. But as the control has no template the overridden method in the control's code-behind is never called.
Is there some way I can override the OnApplyTemplate method for the templated element in the control's code behind?
What is the base-class. You can't override OnApplyTemplate if the underlying class doesn't support templates. I think you'd be best to just change the tooltip style when the value is set (as its unlikely to show up anyway).
Any reason you can't just do GetTemplateChild as the path changes? That should be late enough in the lifetime.

Silverlight databinding a textBlock in another user control

I have a small usercontrol that basically increments or decrements a value by one. The user control has two buttons(one to add and the other to subtract) and a textBlock that is used to display the value.
I am going to have multiple instance of this usercontrol in another usercontrol so I can manipulate values of a dataclass that has an INotifyPropertyChanged interface. My question is how can I databind the textBlock of the value changing usercontrol to the usercontrol I instansiated it in?
First, I want to state that Silverlight 2 does not support element to element binding. That feature is added in Silverlight 3 (out in Beta now). Having said that, I don't think you want to bind controls together anyway. It sounds like you're trying to build a NumericUpDown control and you probably have some class in code behind that's actually doing the incrementing and decrementing.
If that's the case, you can simply subscribe to the click handlers and call a method on your model like Increment or Decrement. Your model can expose a property for the current value and that property is what is bound to your text box.
Now if you're actually trying to build a NumericUpDown control, you might want to check out the Silverlight Toolkit. The toolkit already includes this control and it also supports data binding.
Check out the NumericUpDown Control here and download the toolkit here.
Finally, binding from a child control to a parent control really isn't any different. The parent UserControl has a DataContext and all child controls inherit that. Each individual child control can also have its DataContext set. Binding expressions are always relative to the DataContext and the DataContext can be set in code. In your case, probably to a model of some sort.
I hope that helps.

Resources