wpf - utilities to get the default Control temp...

it is a common scenario when you sometime want to change the default template for a built-in controls, for example, when you are styling a built-in control or when you are extending a default control to fullfil some new features (adding new capability).
However, it is not exposed on the default template definition, and because of the xaml definition is closed to the client, you won't be able to reflect and view the content of the Xaml to get what you want.. 
but the world is not closed to you, Control.Template property exposed the compiled Control template, the only thing you need to do is to feed that to a XamlWriter. and this is viable. 
In this post, I will reference the post from the Book "Pro Wpf in C# 2010 - Windows Presentation Foundation in .Net 4.0" , in chapter 17, Control template.  
Basically the left is a explorer, which list all the controls, and the right is the Viewer Box, which has the template rendered as String.

Here is the code:

<Window x:Class="ControlTemplateExplorer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150"/>
            <ColumnDefinition Width="2"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

            <ListView x:Name="listTypes" Grid.Column="0" Grid.Row="0" DisplayMemberPath="Name" SelectionChanged="listTypes_SelectionChanged"/>
        
        <GridSplitter 
            ResizeDirection="Columns"
            VerticalAlignment="Stretch"
            HorizontalAlignment="Stretch"
            ShowsPreview="True"
            Grid.Column="1"
            />
        <!-- ViewBox ??-->
        <!-- DocumentViewer ??-->
        <!--http://stackoverflow.com/questions/1981137/c-sharp-wpf-scrollviewer-textblock-troubles-->
        <ScrollViewer  Grid.Column="2" Grid.Row="0"
                       HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" 
                       x:Name="Scroller"
                       >
            <TextBox x:Name="txtTemplate" 
                     HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                     MinWidth="100" Width="{Binding ElementName=Scroller, Path=ViewportWidth}" TextWrapping="Wrap"
                     />
        </ScrollViewer>

        <Grid x:Name="grid" Visibility="Collapsed" >
        </Grid>
    </Grid>
</Window>

and in the code behind, we have this; 

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xml;

namespace ControlTemplateExplorer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += Window_Loaded;
        }

        private void Window_Loaded(object sender, EventArgs e)
        {
            Type controlType = typeof (Control);

            List<Type> derivedTypes = new List<Type>();

            Assembly assembly = Assembly.GetAssembly(typeof (Control));

            // Search all the types in teh assembly where the Control class is defined. 
            foreach (Type type in assembly.GetTypes())
            {
                //Only add a type of the list if it's a Control, a concrete class
                // and public 
                if (type.IsSubclassOf(controlType) && !type.IsAbstract && type.IsPublic)
                {
                    derivedTypes.Add(type);
                }
            }

            // sort the types, the custom TypeComparer class orders types
            // alphabetically by type name.
            derivedTypes.Sort(new TypeComparer());

            // How the list of the types
            listTypes.ItemsSource = derivedTypes;
        }

        private void listTypes_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                // Get the Selected type.
                Type type = (Type) listTypes.SelectedItem;

                // Instance the type.
                ConstructorInfo info = type.GetConstructor(System.Type.EmptyTypes);
                Control control = (Control)info.Invoke(null);

                // Add it to the grid (but keep it hidden)
                control.Visibility = Visibility.Collapsed;
                grid.Children.Add(control);

                // Get the template
                ControlTemplate template = control.Template;

                // Get the Xaml for the template
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                StringBuilder sb = new StringBuilder();

                XmlWriter writer = XmlWriter.Create(sb, settings);
                XamlWriter.Save(template, writer);

                // Display the template
                txtTemplate.Text = sb.ToString();

                // Remove the control from the Grid
                grid.Children.Remove(control);
            }
            catch (Exception err)
            {
                txtTemplate.Text = "<Error generating template: " + err.Message + " >";
            }
        }
    }

    class TypeComparer : IComparer<Type>
    {
        #region Implementation of IComparer<in Type>

        public int Compare(Type x, Type y)
        {
            return string.Compare(x.Name, y.Name);
        }

        #endregion
    }
}
When the program runs, it has the following. 

wpf - utilities to get the default Control temp..._第1张图片



你可能感兴趣的:(WPF)