How to set Control Template in code?
I have this in XAML
<ControlTemplate TargetType="{x:Type Button}">
<Image ...>
</ControlTemplate>
I want to achieve same in C# code. How can I achieve this?
ControlTemplate ct = new ControlTemplate();..
Image img = new Image();..
Now how to assign this Image to Control template? Can we do this or Am I missing any concept here?
Solution 1:
Creating template in codebehind is not a good idea, in theory one would do this by defining the ControlTemplate.VisualTree
which is a FrameworkElementFactory
.
ControlTemplate template = new ControlTemplate(typeof(Button));
var image = new FrameworkElementFactory(typeof(Image));
template.VisualTree = image;
Assigning properties is very roundabout since you need to use SetValue
and SetBinding
:
image.SetValue(Image.SourceProperty, ...);
Also, about the (previously) accepted answer and the stuff quoted:
Setting the ControlTemplate programmatically is just like using XAML because we have to use the XamlReader class.
That statement is just wrong, we do not "have to".
If i assign templates at run time i define them as a resource which i can load if i need it.
Edit: According to the documentation FrameworkElementFactory
is deprecated:
This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; not all of the template functionality is available when you create a template using this class. The recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class.
I wonder if this recommendation is such a good idea. Personally i would still go with defining the template as a resource in XAML if i can avoid doing it with strings and the XamlReader
.
Solution 2:
http://www.eggheadcafe.com/sample-code/SilverlightWPFandXAML/73fdb6a2-6044-4c43-8766-afa12618ddc1/set-controltemplate-programmatically.aspx
Setting the ControlTemplate programmatically is just like using XAML because we have to use the XamlReader class. For example, here is the code to set a button's template, assuming that we want to set a button's template after it is loaded.
private void Button_Loaded(object sender, RoutedEventArgs e) {
var button = sender as Button;
string template =
"<ControlTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
TargetType=\"Button\">" +
"<Border>" +
"<ContentPresenter/>" +
"</Border>" +
"</ControlTemplate>";
button.Template = (ControlTemplate)XamlReader.Parse(template);
}
Since we used a string for specifying the XAML code for the template, we can use the XamlReader's Parse method. The XamlReader also has a Load method, which is primarily used for streams or XAML or XML readers. Notice that we have to include the XML namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation because the ControlTemplate, Border, and other controls we need are defined there. If we did not include it, we'll encounter a runtime exception. Basically, we have to put the namespaces needed by the template.