WPF Control Templates (part 1)
Styles and Templates can change the appearance of elements. So what is the difference then?
Templates are far more complex. Styles are mainly adjusting existing properties. You could say that Styles are like Face-Lifting whereas Templates are rather entire face replacements. Elements get new visual trees that can consist of other elements. This is not the case for Styles.
Before we start creating our own templates let’s have a look at the existing standard control templates. Today’s example code reads these Templates from the assembly and prints them in a TextBox.
Take a stroll and get a feeling for them.
Surely this is not for beginners. My advice is to copy, paste and reuse existing professional XAML rather than spending your precious time to figure out every little issue yourself. And today’s source code aims at exactly that approach.
<Application x:Class="WpfTemplates.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ShutdownMode="OnMainWindowClose" StartupUri="MainWindow.xaml"> <Application.Resources> </Application.Resources> </Application> <Window x:Class="WpfTemplates.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="Window_Loaded" Title="MainWindow" Height="350" Width="525"> <DockPanel LastChildFill="True"> <ListBox DockPanel.Dock="Left" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" MinWidth="100" /> <Grid DockPanel.Dock="Right" Name="dummyGrid" Width="0" /> <TextBox DockPanel.Dock="Left" Text="{Binding XAML}" TextWrapping="NoWrap" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" FontFamily="Courier New" /> </DockPanel> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Markup; using System.Xml; namespace WpfTemplates { public partial class MainWindow : Window { private class Data { public Type Type { get; set; } public string XAML { get; set; } public Data(Type xType) { this.Type = xType; XAML = "#N/A"; } public override string ToString() { return Type.Name; } } // class public MainWindow() { InitializeComponent(); } // private void Window_Loaded(object sender, RoutedEventArgs e) { List<Data> lData = new List<Data>(); Assembly lAssembly = Assembly.GetAssembly(typeof(Control)); Type lControlType = typeof(Control); List<Data> lTypes = (from t in lAssembly.GetTypes().AsParallel() where t.IsSubclassOf(lControlType) && t.IsPublic && !t.IsAbstract orderby t.Name ascending select new Data(t)).ToList(); InsertXaml(lTypes); DataContext = lTypes; } // private void InsertXaml(List<Data> xTypes) { XmlWriterSettings lXmlWriterSettings = new XmlWriterSettings(); lXmlWriterSettings.Indent = true; StringBuilder lStringBuilder = new StringBuilder(); // for output foreach (Data lData in xTypes) { try { ConstructorInfo lConstructorInfo = lData.Type.GetConstructor(System.Type.EmptyTypes); if (lConstructorInfo == null) { lData.XAML = lData.Type.Name + " control cannot be instantiated."; continue; } Control lControl = lConstructorInfo.Invoke(null) as Control; // create an instance lControl.Visibility = System.Windows.Visibility.Collapsed; bool lIsNullTemplate = (lControl.Template == null); if (lIsNullTemplate) dummyGrid.Children.Add(lControl); // add a collapsed (invisible) control to get access to the template ControlTemplate lControlTemplate = lControl.Template; // now not null anymore using (XmlWriter lXmlWriter = XmlWriter.Create(lStringBuilder, lXmlWriterSettings)) { // will write to StringBuilder XamlWriter.Save(lControlTemplate, lXmlWriter); lData.XAML = lStringBuilder.ToString(); } lStringBuilder.Clear(); if (lIsNullTemplate) dummyGrid.Children.Remove(lControl); } catch (Exception ex) { lData.XAML = lData.Type.Name + " control cannot be added to the grid.\n\nException message:\n" + ex.Message; } } } // } // class } // namespace
Posted on April 22, 2014, in Advanced, Professional, WPF and tagged advanced, C#, C-sharp, programming, Source code, Templates, WPF. Bookmark the permalink. 1 Comment.
Pingback: WPF Datagrid formatting (part 2, advanced) | C# Hardcore Programming